Skip to content

Commit f870a59

Browse files
committed
Added a second email to be sent as a sort-of two step process.
1 parent da10911 commit f870a59

File tree

9 files changed

+217
-42
lines changed

9 files changed

+217
-42
lines changed

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

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.objectcomputing.checkins.services.memberprofile.*;
99
import io.micronaut.core.annotation.Nullable;
1010
import io.micronaut.core.convert.format.Format;
11+
import io.micronaut.http.HttpStatus;
1112
import io.micronaut.http.HttpResponse;
1213
import io.micronaut.http.MediaType;
1314
import io.micronaut.http.annotation.*;
@@ -66,39 +67,16 @@ public FeedbackRequestExternalRecipientController(
6667
*/
6768
@Get("/{id}")
6869
public HttpResponse<FeedbackRequestResponseDTO> getById(UUID id) {
69-
FeedbackRequest feedbackRequest = feedbackReqServices.getById(id);
70-
if (feedbackRequest.getExternalRecipientId() == null) {
71-
throw new BadArgException("This feedback request is not for an external recipient");
72-
}
70+
FeedbackRequest feedbackRequest = getExternal(id);
7371
return feedbackRequest == null ? HttpResponse.notFound() : HttpResponse.ok(feedbackRequestFromEntity(feedbackRequest))
7472
.headers(headers -> headers.location(URI.create("/feedback_request" + feedbackRequest.getId())));
7573
}
7674

77-
/**
78-
* Find feedback requests by values
79-
* @param creatorId {@link UUID} ID of the creator
80-
* @param requesteeId {@link UUID} ID of the requestee
81-
* @param recipientId {@link UUID} ID of the recipient
82-
* @param oldestDate {@link LocalDate} The oldest date to search for
83-
* @param reviewPeriodId {@link UUID} ID of the review period
84-
* @param templateId {@link UUID} ID of the template
85-
* @param externalRecipientId {@link UUID} ID of the external recipient
86-
* @return {@link FeedbackRequestResponseDTO}
87-
*/
88-
/*
89-
@Get("/{?creatorId,requesteeId,recipientId,oldestDate,reviewPeriodId,templateId,externalRecipientId,requesteeIds}")
90-
public List<FeedbackRequestResponseDTO> findByValues(@Nullable UUID creatorId, @Nullable UUID requesteeId, @Nullable UUID recipientId, @Nullable @Format("yyyy-MM-dd") LocalDate oldestDate, @Nullable UUID reviewPeriodId, @Nullable UUID templateId, UUID externalRecipientId, @Nullable List<UUID> requesteeIds) {
91-
return feedbackReqServices.findByValues(creatorId, requesteeId, recipientId, oldestDate, reviewPeriodId, templateId, externalRecipientId, requesteeIds)
92-
.stream()
93-
.map(this::feedbackRequestFromEntity)
94-
.toList();
95-
}
96-
*/
97-
98-
@Get("/hello")
99-
@Produces(MediaType.TEXT_HTML)
100-
public String hello() {
101-
return "<html><body><h1>Hello, World!</h1></body></html>";
75+
@Get("/verify/{id}")
76+
public HttpStatus verifyRequest(UUID id) {
77+
FeedbackRequest feedbackRequest = getExternal(id);
78+
return feedbackReqServices.verifyExternal(feedbackRequest)
79+
? HttpStatus.OK : HttpStatus.UNPROCESSABLE_ENTITY;
10280
}
10381

10482
@Get("/submitForExternalRecipient/{id}")
@@ -123,6 +101,14 @@ public HttpResponse<FeedbackRequestResponseDTO> update(@Body @Valid @NotNull Fee
123101
.headers(headers -> headers.location(URI.create("/feedback_request/" + savedFeedback.getId())));
124102
}
125103

104+
private FeedbackRequest getExternal(UUID id) {
105+
FeedbackRequest feedbackRequest = feedbackReqServices.getById(id);
106+
if (feedbackRequest.getExternalRecipientId() == null) {
107+
throw new BadArgException("This feedback request is not for an external recipient");
108+
}
109+
return feedbackRequest;
110+
}
111+
126112
private FeedbackRequestResponseDTO feedbackRequestFromEntity(FeedbackRequest feedbackRequest) {
127113
FeedbackRequestResponseDTO dto = new FeedbackRequestResponseDTO();
128114
dto.setId(feedbackRequest.getId());

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ public interface FeedbackRequestServices {
1616
List<FeedbackRequest> findByValues(UUID creatorId, UUID requesteeId, UUID recipientId, LocalDate oldestDate, UUID reviewPeriodId, UUID templateId, UUID externalRecipientId, List<UUID> requesteeIds);
1717

1818
boolean selfRevieweeIsCurrentUserReviewee(FeedbackRequest request, UUID currentUserId);
19+
20+
boolean verifyExternal(FeedbackRequest feedbackRequest);
1921
}

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

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ private record ReviewPeriodInfo(String subject, LocalDate closeDate) {}
5858
private Readable feedbackRequestTemplate;
5959
@Value("classpath:mjml/external_feedback_request.mjml")
6060
private Readable externalFeedbackRequestTemplate;
61+
@Value("classpath:mjml/external_request_verify.mjml")
62+
private Readable externalRequestVerifyTemplate;
6163
@Value("classpath:mjml/update_request.mjml")
6264
private Readable updateRequestTemplate;
6365
@Value("classpath:mjml/reviewer_email.mjml")
@@ -138,15 +140,41 @@ public FeedbackRequest save(FeedbackRequest feedbackRequest) {
138140
if (feedbackRequest.getDueDate() != null && feedbackRequest.getSendDate().isAfter(feedbackRequest.getDueDate())) {
139141
throw new BadArgException("Send date of feedback request must be before the due date.");
140142
}
141-
String status = feedbackRequest.getSendDate().isAfter(LocalDate.now()) ? "pending" : "sent";
142-
feedbackRequest.setStatus(status);
143+
FeedbackRequestStatus status = feedbackRequest.getSendDate().isAfter(LocalDate.now()) ? FeedbackRequestStatus.PENDING : FeedbackRequestStatus.SENT;
144+
feedbackRequest.setStatus(status.toString());
143145
FeedbackRequest storedRequest = feedbackReqRepository.save(feedbackRequest);
144146
if (feedbackRequest.getSendDate().equals(LocalDate.now())) {
145147
sendNewRequestEmail(storedRequest);
146148
}
147149
return storedRequest;
148150
}
149151

152+
@Override
153+
public boolean verifyExternal(FeedbackRequest feedbackRequest) {
154+
if (feedbackRequest.getExternalRecipientId() == null ||
155+
!feedbackRequest.getStatus().equals(FeedbackRequestStatus.SENT.toString())) {
156+
return false;
157+
}
158+
159+
MemberProfile creator = memberProfileServices.getById(feedbackRequest.getCreatorId());
160+
MemberProfile requestee = memberProfileServices.getById(feedbackRequest.getRequesteeId());
161+
UUID recipientOrExternalRecipientId = feedbackRequest.getExternalRecipientId();
162+
FeedbackExternalRecipient reviewerExternalRecipient = feedbackExternalRecipientServices.getById(recipientOrExternalRecipientId);
163+
String newContent = String.format(
164+
templateToString(externalRequestVerifyTemplate),
165+
reviewerExternalRecipient.getFirstName(),
166+
String.format("%s/externalFeedback/submit?request=%s",
167+
webURL, feedbackRequest.getId().toString())
168+
);
169+
emailSender.sendEmail(
170+
MemberProfileUtils.getFullName(creator),
171+
creator.getWorkEmail(),
172+
notificationSubject, newContent,
173+
reviewerExternalRecipient.getEmail()
174+
);
175+
return true;
176+
}
177+
150178
public void sendNewRequestEmail(FeedbackRequest storedRequest) {
151179
MemberProfile creator = memberProfileServices.getById(storedRequest.getCreatorId());
152180
MemberProfile reviewerMemberProfile;
@@ -162,7 +190,7 @@ public void sendNewRequestEmail(FeedbackRequest storedRequest) {
162190
reviewerExternalRecipient = feedbackExternalRecipientServices.getById(recipientOrExternalRecipientId);
163191
reviewerFirstName = reviewerExternalRecipient.getFirstName();
164192
reviewerEmail = reviewerExternalRecipient.getEmail();
165-
urlFeedbackSubmit = "/externalFeedback/submit?request=";
193+
urlFeedbackSubmit = "/externalFeedback/verify?request=";
166194
template = externalFeedbackRequestTemplate;
167195
} else {
168196
recipientOrExternalRecipientId = storedRequest.getRecipientId();
@@ -184,8 +212,9 @@ public void sendNewRequestEmail(FeedbackRequest storedRequest) {
184212
storedRequest.getDueDate().getMonth(),
185213
storedRequest.getDueDate().getDayOfMonth(),
186214
storedRequest.getDueDate().getYear()),
187-
String.format("%s" + urlFeedbackSubmit + "%s",
188-
webURL, storedRequest.getId().toString())
215+
String.format("%s%s%s",
216+
webURL, urlFeedbackSubmit,
217+
storedRequest.getId().toString())
189218
);
190219
emailSender.sendEmail(
191220
senderName, creator.getWorkEmail(),
@@ -243,7 +272,7 @@ public FeedbackRequest update(FeedbackRequestUpdateDTO feedbackRequestUpdateDTO)
243272
boolean submitDateUpdateAttempted = !Objects.equals(originalFeedback.getSubmitDate(), feedbackRequest.getSubmitDate());
244273

245274
// If a status update is made to anything other than submitted by the requestee, throw an error.
246-
if (!"submitted".equals(feedbackRequest.getStatus())
275+
if (!feedbackRequest.getStatus().equals(FeedbackRequestStatus.SUBMITTED.toString())
247276
&& !Objects.equals(originalFeedback.getStatus(), feedbackRequest.getStatus())
248277
&& currentUserEqualsRequestee) {
249278
throw new PermissionException(NOT_AUTHORIZED_MSG);
@@ -253,10 +282,11 @@ public FeedbackRequest update(FeedbackRequestUpdateDTO feedbackRequestUpdateDTO)
253282
if (!reassignIsPermitted(originalFeedback)) {
254283
throw new PermissionException(NOT_AUTHORIZED_MSG);
255284
}
256-
feedbackRequest.setStatus("sent");
285+
feedbackRequest.setStatus(FeedbackRequestStatus.SENT.toString());
257286
}
258287

259-
if (feedbackRequest.getStatus().equals("canceled") && originalFeedback.getStatus().equals("submitted")) {
288+
if (feedbackRequest.getStatus().equals(FeedbackRequestStatus.CANCELED.toString()) &&
289+
originalFeedback.getStatus().equals(FeedbackRequestStatus.SUBMITTED.toString())) {
260290
throw new BadArgException("Attempted to cancel a feedback request that was already submitted");
261291
}
262292

@@ -292,7 +322,7 @@ public FeedbackRequest update(FeedbackRequestUpdateDTO feedbackRequestUpdateDTO)
292322

293323
MemberProfile requestee = memberProfileServices.getById(storedRequest.getRequesteeId());
294324
// Send email if the feedback request has been reopened for edits
295-
if (originalFeedback.getStatus().equals("submitted") && feedbackRequest.getStatus().equals("sent")) {
325+
if (originalFeedback.getStatus().equals(FeedbackRequestStatus.SUBMITTED.toString()) && feedbackRequest.getStatus().equals(FeedbackRequestStatus.SENT.toString())) {
296326
MemberProfile creator = memberProfileServices.getById(storedRequest.getCreatorId());
297327
String senderName = MemberProfileUtils.getFullName(creator);
298328
String newContent = String.format(
@@ -480,7 +510,7 @@ private boolean updateDueDateIsPermitted(FeedbackRequest feedbackRequest) {
480510
}
481511

482512
private boolean reassignIsPermitted(FeedbackRequest feedbackRequest) {
483-
return isCurrentUserAdminOrOwner(feedbackRequest) && !feedbackRequest.getStatus().equals("submitted");
513+
return isCurrentUserAdminOrOwner(feedbackRequest) && !feedbackRequest.getStatus().equals(FeedbackRequestStatus.SUBMITTED.toString());
484514
}
485515

486516
private boolean isCurrentUserAdminOrOwner(FeedbackRequest feedbackRequest) {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.objectcomputing.checkins.services.feedback_request;
2+
3+
public enum FeedbackRequestStatus {
4+
SENT("sent"),
5+
PENDING("pending"),
6+
SUBMITTED("submitted"),
7+
CANCELED("canceled");
8+
9+
private final String text;
10+
11+
FeedbackRequestStatus(String text) {
12+
this.text = text;
13+
}
14+
15+
@Override
16+
public String toString() {
17+
return text;
18+
}
19+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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-section background-color="#ffffff">
16+
<mj-column>
17+
<mj-text font-size="16px">Hello, %s!</mj-text>
18+
<mj-text font-size="16px">Thank you for taking the time to give us feedback.</mj-text>
19+
<mj-text font-size="16px">Please click <a href="%s">here</a> to begin.</mj-text>
20+
</mj-column>
21+
</mj-section>
22+
<mj-section background-color="#feb672" padding="10px">
23+
<mj-column vertical-align="top" width="100%%">
24+
<mj-text align="center" color="#FFF" font-size="16px">We appreciate your time!</mj-text>
25+
</mj-column>
26+
</mj-section>
27+
</mj-body>
28+
</mjml>

web-ui-external-feedback/src/App.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
1111
import { LocalizationProvider } from '@mui/x-date-pickers';
1212
import { DarkMode, LightMode } from '@mui/icons-material';
1313

14+
import { AppBar } from '@mui/material';
1415
import {
1516
useColorScheme,
1617
experimental_extendTheme as extendTheme,
@@ -95,6 +96,15 @@ function App() {
9596
<ErrorBoundary FallbackComponent={ErrorFallback}>
9697
<div>
9798
<div className="App">
99+
<AppBar position="fixed">
100+
<div style={{ display: 'flex', justifyContent: 'left' }}>
101+
<img
102+
alt="Object Computing, Inc."
103+
src="/externalFeedback/img/ocicube-color.png"
104+
style={{ width: '4%' }}
105+
/>
106+
</div>
107+
</AppBar>
98108
<Routes />
99109
</div>
100110
</div>
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useContext } from 'react';
22
import { Switch, Route } from 'react-router-dom';
33
import { AppContext } from '../../context/AppContext';
4+
import FeedbackVerifyPage from "../../pages/FeedbackVerifyPage.jsx";
45
import FeedbackSubmitPage from "../../pages/FeedbackSubmitPage.jsx";
56
import FeedbackSubmitConfirmation from "../feedback_submit_confirmation/FeedbackSubmitConfirmation.jsx";
67

@@ -9,12 +10,15 @@ export default function Routes() {
910

1011
return (
1112
<Switch>
13+
<Route path="/externalFeedback/verify">
14+
<FeedbackVerifyPage />
15+
</Route>
1216
<Route path="/externalFeedback/submit">
1317
<FeedbackSubmitPage />
1418
</Route>
15-
<Route path="/externalFeedback/confirmation">
16-
<FeedbackSubmitConfirmation />
17-
</Route>
19+
<Route path="/externalFeedback/confirmation">
20+
<FeedbackSubmitConfirmation />
21+
</Route>
1822
</Switch>
1923
);
2024
}

web-ui-external-feedback/src/pages/FeedbackRequestPage.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
max-width: 100%;
55
}
66

7+
.feedback-verify-page {
8+
margin: 4em 2em 0 2em;
9+
height: 100%;
10+
max-width: 70%;
11+
}
12+
713
.header-container {
814
display: flex;
915
flex-direction: row;
@@ -36,6 +42,15 @@
3642
margin: 2rem 5% 0 5%;
3743
}
3844

45+
.feedback-verify-page {
46+
display: flex;
47+
flex-direction: column;
48+
align-items: center;
49+
overflow-x: hidden;
50+
margin: 2rem 5% 0 5%;
51+
width: 70%;
52+
}
53+
3954
.header-container {
4055
margin: 0;
4156
}

0 commit comments

Comments
 (0)