From fd3884961274bb5b09bfb303c121716ab8f2625b Mon Sep 17 00:00:00 2001
From: qweliant
Date: Tue, 13 Feb 2024 14:10:48 -0500
Subject: [PATCH 01/10] 0;9uadd new emails
---
.../evaluations/app/actions/manage/actions.ts | 4 +-
integrations/evaluations/lib/emails.ts | 402 ++++++++++++++++--
2 files changed, 362 insertions(+), 44 deletions(-)
diff --git a/integrations/evaluations/app/actions/manage/actions.ts b/integrations/evaluations/app/actions/manage/actions.ts
index 7de372b5cd..08978cd164 100644
--- a/integrations/evaluations/app/actions/manage/actions.ts
+++ b/integrations/evaluations/app/actions/manage/actions.ts
@@ -9,7 +9,7 @@ import { cookie } from "~/lib/request";
import { isInvited } from "~/lib/types";
import {
scheduleNoReplyNotificationEmail,
- scheduleReminderEmail,
+ scheduleInvitationReminderEmail,
sendInviteEmail,
} from "../../../lib/emails";
import { InviteFormEvaluator } from "./types";
@@ -71,7 +71,7 @@ export const save = async (
// Immediately send the invite email.
await sendInviteEmail(instanceId, pubId, evaluator);
// Scehdule a reminder email to person who was invited to evaluate.
- await scheduleReminderEmail(instanceId, instanceConfig, pubId, evaluator);
+ await scheduleInvitationReminderEmail(instanceId, instanceConfig, pubId, evaluator);
// Schedule no-reply notification email to person who invited the
// evaluator.
await scheduleNoReplyNotificationEmail(
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index ea3918e861..f90ce9ad87 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -29,6 +29,21 @@ export function calculateDeadline(
}
}
+export function getDeadline(
+ instanceConfig: InstanceConfig,
+ evaluator: EvaluatorWhoAccepted & EvaluatorWithInvite
+): Date {
+ return evaluator.deadline
+ ? new Date(evaluator.deadline)
+ : calculateDeadline(
+ {
+ deadlineLength: instanceConfig.deadlineLength,
+ deadlineUnit: instanceConfig.deadlineUnit,
+ },
+ new Date(evaluator.acceptedAt)
+ );
+}
+
const notificationFooter =
'This is an automated email sent from Unjournal. Please contact contact@unjournal.org with any questions.
';
@@ -41,6 +56,7 @@ const makeNoReplyJobKey = (instanceId: string, pubId: string, evaluator: Evaluat
const makeNoSubmitJobKey = (instanceId: string, pubId: string, evaluator: EvaluatorWithInvite) =>
`send-email-${instanceId}-${pubId}-${evaluator.userId}-no-submit`;
+// sent to the community manager
export const scheduleNoReplyNotificationEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -139,6 +155,158 @@ export const unscheduleNoSubmitNotificationEmail = (
return client.unscheduleEmail(instanceId, jobKey);
};
+export const scheduleReminderEmail = async (
+ instanceId: string,
+ instanceConfig: InstanceConfig,
+ pubId: string,
+ evaluator: EvaluatorWithInvite
+) => {
+ const jobKey = makeReminderJobKey(instanceId, pubId, evaluator);
+ const runAt = new Date(evaluator.invitedAt);
+ runAt.setMinutes(runAt.getMinutes() + DAYS_TO_REMIND_EVALUATOR * 24 * 60);
+
+ await client.scheduleEmail(
+ instanceId,
+ {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `Reminder: {{users.invitor.firstName}} {{users.invitor.lastName}} invited you to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" for The Unjournal`,
+ message: evaluator.emailTemplate.message,
+ include: {
+ users: {
+ invitor: evaluator.invitedBy,
+ },
+ pubs: {
+ submission: pubId,
+ },
+ },
+ extra: {
+ accept_link: `Accept`,
+ decline_link: `Decline`,
+ info_link: `More Information`,
+ },
+ },
+ { jobKey, runAt }
+ );
+};
+
+export const sendRequestedInfoNotification = (
+ instanceId: string,
+ instanceConfig: InstanceConfig,
+ pubId: string,
+ evaluator: EvaluatorWithInvite
+) => {
+ return client.sendEmail(instanceId, {
+ to: {
+ userId: evaluator.invitedBy,
+ },
+ subject: `[Unjournal] More Information Request for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `An invited evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}", has requested more information. You may contact them at {{users.evaluator.email}}.
+${notificationFooter}`,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ evaluator: evaluator.userId,
+ },
+ },
+ });
+};
+
+export const sendAcceptedNotificationEmail = (
+ instanceId: string,
+ instanceConfig: InstanceConfig,
+ pubId: string,
+ evaluator: EvaluatorWithInvite
+) => {
+ return client.sendEmail(instanceId, {
+ to: {
+ userId: evaluator.invitedBy,
+ },
+ subject: `[Unjournal] Accepted evaluation for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `An invited evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, has agreed to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}". You may review the status of this and other invitations on the {{extra.manage_link}}.
+${notificationFooter}`,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ evaluator: evaluator.userId,
+ },
+ },
+ extra: {
+ manage_link: `Invite Evaluators page`,
+ },
+ });
+};
+
+export const sendDeclinedNotificationEmail = async (
+ instanceId: string,
+ instanceConfig: InstanceConfig,
+ pubId: string,
+ evaluator: EvaluatorWithInvite
+) => {
+ return client.sendEmail(instanceId, {
+ to: {
+ userId: evaluator.invitedBy,
+ },
+ subject: `[Unjournal] Invited evaluator declines to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `An invited evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, has declined to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}". You may review the status of this and other invitations on the {{extra.manage_link}}.
+${notificationFooter}`,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ evaluator: evaluator.userId,
+ },
+ },
+ extra: {
+ manage_link: `Invite Evaluators page`,
+ },
+ });
+};
+
+export const sendSubmittedNotificationEmail = async (
+ instanceId: string,
+ instanceConfig: InstanceConfig,
+ pubId: string,
+ evaluator: EvaluatorWhoEvaluated
+) => {
+ return client.sendEmail(instanceId, {
+ to: {
+ userId: evaluator.invitedBy,
+ },
+ subject: `[Unjournal] Evaluation submitted for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `An evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, has submitted an evaluation for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}". The submitted evaluation Pub can be viewed here.
+You may review the status of this and other invitations on the {{extra.manage_link}}.
+${notificationFooter}`,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ evaluator: evaluator.userId,
+ },
+ },
+ extra: {
+ manage_link: `Invite Evaluators page`,
+ },
+ });
+};
+
+// sent to the evaluator
+
+/**
+ *
+ * Sends an email to the evaluator with the invitation to evaluate the pub.
+ * @param instanceId
+ * @param pubId
+ * @param evaluator
+ * @returns Promise that resolves to the result of the email send operation.
+ */
export const sendInviteEmail = async (
instanceId: string,
pubId: string,
@@ -166,7 +334,14 @@ export const sendInviteEmail = async (
});
};
-export const scheduleReminderEmail = async (
+/**
+ * Sends an email to the evaluator as a reminder to accept the invitation to evaluate the pub.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ */
+export const scheduleInvitationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
@@ -202,6 +377,13 @@ export const scheduleReminderEmail = async (
);
};
+/**
+ * Cancels the scheduled reminder email for the evaluator to accept the invitation to evaluate the pub.
+ * @param instanceId
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const unscheduleReminderEmail = (
instanceId: string,
pubId: string,
@@ -211,21 +393,21 @@ export const unscheduleReminderEmail = (
return client.unscheduleEmail(instanceId, jobKey);
};
+/**
+ * Sends an email to the evaluator to inform them that their invitation to evaluate the pub has been accepted.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const sendAcceptedEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
evaluator: EvaluatorWhoAccepted
) => {
- const deadline = evaluator.deadline
- ? new Date(evaluator.deadline)
- : calculateDeadline(
- {
- deadlineLength: instanceConfig.deadlineLength,
- deadlineUnit: instanceConfig.deadlineUnit,
- },
- new Date(evaluator.acceptedAt)
- );
+ const deadline = getDeadline(instanceConfig, evaluator);
await client.sendEmail(instanceId, {
to: {
userId: evaluator.userId,
@@ -261,108 +443,244 @@ export const sendAcceptedEmail = async (
});
};
-export const sendRequestedInfoNotification = (
+// export const sendPromptEvalBonusReminderEmail = () => {};
+// export const sendFinalPromptEvalBonusReminderEmail = () => {};
+// export const sendEvalutaionReminderEmail = () => {};
+// export const sendFinalEvaluationReminderEmail = () => {};
+// export const sendFollowUpToEvaluationReminderEmail = () => {};
+// export const sendNoticeOfNoSubmitEmail = () => {};
+
+// Send prompt evaluation bonus reminder email
+export const sendPromptEvalBonusReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
- evaluator: EvaluatorWithInvite
+ evaluator: EvaluatorWhoAccepted
) => {
+ const deadline = getDeadline(instanceConfig, evaluator);
+ const reminderDeadline = new Date(deadline.getTime() - 14 * (1000 * 60 * 60 * 24));
return client.sendEmail(instanceId, {
to: {
- userId: evaluator.invitedBy,
+ userId: evaluator.userId,
},
- subject: `[Unjournal] More Information Request for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
- message: `An invited evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}", has requested more information. You may contact them at {{users.evaluator.email}}.
-${notificationFooter}`,
+ subject: `[Unjournal] Reminder to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" for prompt evaluation bonus`,
+ message: `Hi {{user.firstName}},
+ Thanks again for agreeing to evaluate "{{pubs.submission.values["${
+ instanceConfig.titleFieldSlug
+ }"]}}" for The Unjournal.
+ This note is a reminder to submit your evaluation by ${new Date(
+ reminderDeadline.getTime() - 14 * (1000 * 60 * 60 * 24)
+ ).toLocaleDateString()} to receive a $100 “prompt evaluation bonus,” in addition to your baseline compensation. Please note that after ${new Date(
+ deadline.getTime()
+ ).toLocaleDateString()} we will consider re-assigning the evaluation, and later submissions may not be eligible for the full baseline compensation.
+ Please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
+ If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
+ Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.
+ Thanks and best wishes,
+ {{users.invitor.firstName}} {{users.invitor.lastName}}
+ Unjournal.org
`,
include: {
pubs: {
submission: pubId,
},
users: {
- evaluator: evaluator.userId,
+ invitor: evaluator.invitedBy,
},
},
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
+ },
});
};
-export const sendAcceptedNotificationEmail = (
+// Send final prompt evaluation bonus reminder email
+export const sendFinalPromptEvalBonusReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
- evaluator: EvaluatorWithInvite
+ evaluator: EvaluatorWhoAccepted
) => {
+ const deadline = getDeadline(instanceConfig, evaluator);
+ const reminderDeadline = new Date(deadline.getTime() - 14 * (1000 * 60 * 60 * 24));
return client.sendEmail(instanceId, {
to: {
- userId: evaluator.invitedBy,
+ userId: evaluator.userId,
},
- subject: `[Unjournal] Accepted evaluation for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
- message: `An invited evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, has agreed to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}". You may review the status of this and other invitations on the {{extra.manage_link}}.
-${notificationFooter}`,
+ subject: `[Unjournal] Final Reminder: Submit evaluation for prompt bonus "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `Hi {{user.firstName}},
+ This is a final reminder to submit your evaluation for "{{pubs.submission.values["${
+ instanceConfig.titleFieldSlug
+ }"]}}" by the deadline ${new Date(
+ reminderDeadline.getTime()
+ ).toLocaleDateString()} to receive the $100 “prompt evaluation bonus.”
+ If you haven't already, please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
+ If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
+ Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.
+ Thanks and best wishes,
+ {{users.invitor.firstName}} {{users.invitor.lastName}}
+ Unjournal.org
`,
include: {
pubs: {
submission: pubId,
},
users: {
- evaluator: evaluator.userId,
+ invitor: evaluator.invitedBy,
},
},
extra: {
- manage_link: `Invite Evaluators page`,
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
});
};
-export const sendDeclinedNotificationEmail = async (
+// Send evaluation reminder email
+export const sendEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
- evaluator: EvaluatorWithInvite
+ evaluator: EvaluatorWhoAccepted
) => {
+ // Calculate the deadline for the reminder email
+ const deadline = getDeadline(instanceConfig, evaluator);
+
return client.sendEmail(instanceId, {
to: {
- userId: evaluator.invitedBy,
+ userId: evaluator.userId,
},
- subject: `[Unjournal] Invited evaluator declines to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
- message: `An invited evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, has declined to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}". You may review the status of this and other invitations on the {{extra.manage_link}}.
-${notificationFooter}`,
+ subject: `[Unjournal] Reminder to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" by next week`,
+ message: `Hi {{user.firstName}},
+ Thank you again for agreeing to evaluate "{{pubs.submission.values["${
+ instanceConfig.titleFieldSlug
+ }"]}}" for The Unjournal.
+ This note is a reminder that your evaluation should be submitted by ${new Date(
+ deadline.getTime()
+ ).toLocaleDateString()} (next week). Please note that after that date we will consider re-assigning the evaluation, and later submissions may not be eligible for the full baseline compensation.
+ Please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
+ If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
+ Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.
+ Thanks and best wishes,
+ {{users.invitor.firstName}} {{users.invitor.lastName}}
+ Unjournal.org
`,
include: {
pubs: {
submission: pubId,
},
users: {
- evaluator: evaluator.userId,
+ invitor: evaluator.invitedBy,
},
},
extra: {
- manage_link: `Invite Evaluators page`,
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
});
};
-export const sendSubmittedNotificationEmail = async (
+// Send final evaluation reminder email
+export const sendFinalEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
- evaluator: EvaluatorWhoEvaluated
+ evaluator: EvaluatorWhoAccepted
) => {
return client.sendEmail(instanceId, {
to: {
- userId: evaluator.invitedBy,
+ userId: evaluator.userId,
},
- subject: `[Unjournal] Evaluation submitted for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
- message: `An evaluator, {{users.evaluator.firstName}} {{users.evaluator.lastName}}, has submitted an evaluation for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}". The submitted evaluation Pub can be viewed here.
-You may review the status of this and other invitations on the {{extra.manage_link}}.
-${notificationFooter}`,
+ subject: `[Unjournal] Final Reminder: Evaluation due tomorrow`,
+ message: `Hi {{user.firstName}},
+ This note is a final reminder that your evaluation for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" is due tomorrow. Please make sure to submit your evaluation by the deadline.
+ If you haven't already, please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
+ If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
+ Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.
+ Thanks and best wishes,
+ {{users.invitor.firstName}} {{users.invitor.lastName}}
+ Unjournal.org
`,
include: {
pubs: {
submission: pubId,
},
users: {
- evaluator: evaluator.userId,
+ invitor: evaluator.invitedBy,
},
},
extra: {
- manage_link: `Invite Evaluators page`,
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
+ },
+ });
+};
+
+// Send follow-up to evaluation reminder email
+export const sendFollowUpToFinalEvaluationReminderEmail = async (
+ instanceId: string,
+ instanceConfig: InstanceConfig,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => {
+ const deadline = getDeadline(instanceConfig, evaluator);
+ return client.sendEmail(instanceId, {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Follow-up: Evaluation overdue, to be reassigned`,
+ message: `Hi {{user.firstName}},
+ This note is a reminder that your evaluation for "{{pubs.submission.values["${
+ instanceConfig.titleFieldSlug
+ }"]}}" is overdue. We are now planning to reassign the evaluation to another evaluator.
+ If you have completed the evaluation but forgot to submit it, please submit your evaluation and rating today using this evaluation form. If we don't hear from you by the end of ${new Date(
+ deadline.getTime()
+ ).toLocaleDateString()}, we will remove you from this assignment and you will no longer be eligible for compensation.
+ If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
+ Thanks and best wishes,
+ {{users.invitor.firstName}} {{users.invitor.lastName}}
+ Unjournal.org
`,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
+ },
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
+ },
+ });
+};
+
+// Send notice of no submit email
+export const sendNoticeOfNoSubmitEmail = async (
+ instanceId: string,
+ instanceConfig: InstanceConfig,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => {
+ const deadline = getDeadline(instanceConfig, evaluator);
+ return client.sendEmail(instanceId, {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Evaluation not submitted for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `Hi {{user.firstName}},
+ This is to inform you that you have not submitted an evaluation for "{{pubs.submission.values["${
+ instanceConfig.titleFieldSlug
+ }"]}}", which was due on ${new Date(deadline.getTime()).toLocaleDateString()}.
+ If you have completed the evaluation but forgot to submit it, please submit your evaluation and rating today using this evaluation form. If we don't hear from you by the end of ${new Date(
+ deadline.getTime()
+ ).toLocaleDateString()}, we will remove you from this assignment and you will no longer be eligible for compensation.
+ If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
+ Thanks and best wishes,
+ {{users.invitor.firstName}} {{users.invitor.lastName}}
+ Unjournal.org
`,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
+ },
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
});
};
From b63e0845d26d909380abc2698629609fe94c6491 Mon Sep 17 00:00:00 2001
From: qweliant
Date: Tue, 13 Feb 2024 15:33:24 -0500
Subject: [PATCH 02/10] todo add runAt
---
.../app/actions/evaluate/evaluate.tsx | 10 +---
.../app/actions/respond/actions.ts | 1 -
integrations/evaluations/lib/emails.ts | 58 +------------------
3 files changed, 3 insertions(+), 66 deletions(-)
diff --git a/integrations/evaluations/app/actions/evaluate/evaluate.tsx b/integrations/evaluations/app/actions/evaluate/evaluate.tsx
index baa483e466..8f997d51c0 100644
--- a/integrations/evaluations/app/actions/evaluate/evaluate.tsx
+++ b/integrations/evaluations/app/actions/evaluate/evaluate.tsx
@@ -101,15 +101,7 @@ export function Evaluate(props: Props) {
const submissionUrl = pub.values["unjournal:url"] as string;
const submissionTitle = pub.values[props.instanceConfig.titleFieldSlug] as string;
const submissionAbstract = pub.values["unjournal:description"] as string;
- const deadline = props.evaluator.deadline
- ? new Date(props.evaluator.deadline)
- : calculateDeadline(
- {
- deadlineLength: props.instanceConfig.deadlineLength,
- deadlineUnit: props.instanceConfig.deadlineUnit,
- },
- new Date(props.evaluator.acceptedAt)
- );
+ const deadline = getDeadline(props.instanceConfig, props.evaluator);
return (
<>
diff --git a/integrations/evaluations/app/actions/respond/actions.ts b/integrations/evaluations/app/actions/respond/actions.ts
index 357dc1ba62..99f2d0ca50 100644
--- a/integrations/evaluations/app/actions/respond/actions.ts
+++ b/integrations/evaluations/app/actions/respond/actions.ts
@@ -39,7 +39,6 @@ export const accept = async (instanceId: string, pubId: string) => {
...evaluator,
status: "accepted",
acceptedAt: new Date().toString(),
- deadline: new Date(Date.now()),
};
const deadline = calculateDeadline(
{
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index f90ce9ad87..2b6fcc5d77 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -29,10 +29,7 @@ export function calculateDeadline(
}
}
-export function getDeadline(
- instanceConfig: InstanceConfig,
- evaluator: EvaluatorWhoAccepted & EvaluatorWithInvite
-): Date {
+export function getDeadline(instanceConfig: InstanceConfig, evaluator: EvaluatorWhoAccepted): Date {
return evaluator.deadline
? new Date(evaluator.deadline)
: calculateDeadline(
@@ -109,15 +106,7 @@ export const scheduleNoSubmitNotificationEmail = async (
evaluator: EvaluatorWhoAccepted
) => {
const jobKey = makeNoSubmitJobKey(instanceId, pubId, evaluator);
- const deadline = evaluator.deadline
- ? new Date(evaluator.deadline)
- : calculateDeadline(
- {
- deadlineLength: instanceConfig.deadlineLength,
- deadlineUnit: instanceConfig.deadlineUnit,
- },
- new Date(evaluator.acceptedAt)
- );
+ const deadline = getDeadline(instanceConfig, evaluator);
const runAt = deadline;
await client.scheduleEmail(
@@ -155,42 +144,6 @@ export const unscheduleNoSubmitNotificationEmail = (
return client.unscheduleEmail(instanceId, jobKey);
};
-export const scheduleReminderEmail = async (
- instanceId: string,
- instanceConfig: InstanceConfig,
- pubId: string,
- evaluator: EvaluatorWithInvite
-) => {
- const jobKey = makeReminderJobKey(instanceId, pubId, evaluator);
- const runAt = new Date(evaluator.invitedAt);
- runAt.setMinutes(runAt.getMinutes() + DAYS_TO_REMIND_EVALUATOR * 24 * 60);
-
- await client.scheduleEmail(
- instanceId,
- {
- to: {
- userId: evaluator.userId,
- },
- subject: `Reminder: {{users.invitor.firstName}} {{users.invitor.lastName}} invited you to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" for The Unjournal`,
- message: evaluator.emailTemplate.message,
- include: {
- users: {
- invitor: evaluator.invitedBy,
- },
- pubs: {
- submission: pubId,
- },
- },
- extra: {
- accept_link: `Accept`,
- decline_link: `Decline`,
- info_link: `More Information`,
- },
- },
- { jobKey, runAt }
- );
-};
-
export const sendRequestedInfoNotification = (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -443,13 +396,6 @@ export const sendAcceptedEmail = async (
});
};
-// export const sendPromptEvalBonusReminderEmail = () => {};
-// export const sendFinalPromptEvalBonusReminderEmail = () => {};
-// export const sendEvalutaionReminderEmail = () => {};
-// export const sendFinalEvaluationReminderEmail = () => {};
-// export const sendFollowUpToEvaluationReminderEmail = () => {};
-// export const sendNoticeOfNoSubmitEmail = () => {};
-
// Send prompt evaluation bonus reminder email
export const sendPromptEvalBonusReminderEmail = async (
instanceId: string,
From 448ec8805d11b1b8311d86d5c3e29dd4bee5bb09 Mon Sep 17 00:00:00 2001
From: qweliant
Date: Wed, 14 Feb 2024 14:08:02 -0500
Subject: [PATCH 03/10] update name
---
integrations/evaluations/app/actions/respond/actions.ts | 7 ++++---
integrations/evaluations/lib/emails.ts | 3 +--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/integrations/evaluations/app/actions/respond/actions.ts b/integrations/evaluations/app/actions/respond/actions.ts
index 99f2d0ca50..4d81b67946 100644
--- a/integrations/evaluations/app/actions/respond/actions.ts
+++ b/integrations/evaluations/app/actions/respond/actions.ts
@@ -8,7 +8,7 @@ import {
sendDeclinedNotificationEmail,
sendRequestedInfoNotification,
unscheduleNoReplyNotificationEmail,
- unscheduleReminderEmail,
+ unscheduleInvitationReminderEmail,
calculateDeadline,
} from "~/lib/emails";
import { getInstanceConfig, getInstanceState, setInstanceState } from "~/lib/instance";
@@ -50,13 +50,14 @@ export const accept = async (instanceId: string, pubId: string) => {
evaluator.deadline = deadline;
await setInstanceState(instanceId, pubId, instanceState);
// Unschedule reminder email.
- await unscheduleReminderEmail(instanceId, pubId, evaluator);
+ await unscheduleInvitationReminderEmail(instanceId, pubId, evaluator);
// Unschedule no-reply notification email.
await unscheduleNoReplyNotificationEmail(instanceId, pubId, evaluator);
// Immediately send accepted notification email.
await sendAcceptedNotificationEmail(instanceId, instanceConfig, pubId, evaluator);
// Immediately send accepted email to evaluator.
await sendAcceptedEmail(instanceId, instanceConfig, pubId, evaluator);
+
// Schedule no-submit notification email.
await scheduleNoSubmitNotificationEmail(instanceId, instanceConfig, pubId, evaluator);
return { success: true };
@@ -84,7 +85,7 @@ export const decline = async (instanceId: string, pubId: string) => {
evaluator = instanceState[user.id] = { ...evaluator, status: "declined" };
await setInstanceState(instanceId, pubId, instanceState);
// Unschedule reminder email.
- await unscheduleReminderEmail(instanceId, pubId, evaluator);
+ await unscheduleInvitationReminderEmail(instanceId, pubId, evaluator);
// Unschedule no-reply notification email.
await unscheduleNoReplyNotificationEmail(instanceId, pubId, evaluator);
// Immediately send declined notification email.
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index 2b6fcc5d77..48efe69cec 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -337,7 +337,7 @@ export const scheduleInvitationReminderEmail = async (
* @param evaluator
* @returns
*/
-export const unscheduleReminderEmail = (
+export const unscheduleInvitationReminderEmail = (
instanceId: string,
pubId: string,
evaluator: EvaluatorWithInvite
@@ -486,7 +486,6 @@ export const sendEvaluationReminderEmail = async (
pubId: string,
evaluator: EvaluatorWhoAccepted
) => {
- // Calculate the deadline for the reminder email
const deadline = getDeadline(instanceConfig, evaluator);
return client.sendEmail(instanceId, {
From 5e26f646815766ffc6df2d1fb05547a852c2d217 Mon Sep 17 00:00:00 2001
From: qweliant
Date: Wed, 14 Feb 2024 17:28:52 -0500
Subject: [PATCH 04/10] handle unscheduling
---
.../app/actions/evaluate/actions.ts | 10 ++-
.../app/actions/respond/actions.ts | 39 ++++++++++--
integrations/evaluations/lib/emails.ts | 63 +++++++++++++++++--
packages/sdk/src/client.ts | 1 -
4 files changed, 100 insertions(+), 13 deletions(-)
diff --git a/integrations/evaluations/app/actions/evaluate/actions.ts b/integrations/evaluations/app/actions/evaluate/actions.ts
index 9182a2802c..1a71159e13 100644
--- a/integrations/evaluations/app/actions/evaluate/actions.ts
+++ b/integrations/evaluations/app/actions/evaluate/actions.ts
@@ -3,7 +3,11 @@
import { PubValues } from "@pubpub/sdk";
import { revalidatePath } from "next/cache";
import { expect } from "utils";
-import { sendSubmittedNotificationEmail, unscheduleNoSubmitNotificationEmail } from "~/lib/emails";
+import {
+ sendSubmittedNotificationEmail,
+ unscheduleAllDeadlineReminderEmails,
+ unscheduleNoSubmitNotificationEmail,
+} from "~/lib/emails";
import { getInstanceConfig, getInstanceState, setInstanceState } from "~/lib/instance";
import { client } from "~/lib/pubpub";
import { cookie } from "~/lib/request";
@@ -37,8 +41,10 @@ export const submit = async (instanceId: string, pubId: string, values: PubValue
evaluationPubId: pub.id,
};
await setInstanceState(instanceId, pubId, instanceState);
- // Unschedule no-submit notification email.
+ // Unschedule no-submit notification email for manager.
await unscheduleNoSubmitNotificationEmail(instanceId, pubId, evaluator);
+ // unschedule dealine reminder emails.
+ await unscheduleAllDeadlineReminderEmails(instanceId, pubId, evaluator);
// Immediately send submitted notification email.
await sendSubmittedNotificationEmail(instanceId, instanceConfig, pubId, evaluator);
revalidatePath("/");
diff --git a/integrations/evaluations/app/actions/respond/actions.ts b/integrations/evaluations/app/actions/respond/actions.ts
index 4d81b67946..911934a758 100644
--- a/integrations/evaluations/app/actions/respond/actions.ts
+++ b/integrations/evaluations/app/actions/respond/actions.ts
@@ -10,6 +10,12 @@ import {
unscheduleNoReplyNotificationEmail,
unscheduleInvitationReminderEmail,
calculateDeadline,
+ schedulePromptEvalBonusReminderEmail,
+ scheduleFinalPromptEvalBonusReminderEmail,
+ scheduleEvaluationReminderEmail,
+ scheduleFinalEvaluationReminderEmail,
+ scheduleFollowUpToFinalEvaluationReminderEmail,
+ sendNoticeOfNoSubmitEmail,
} from "~/lib/emails";
import { getInstanceConfig, getInstanceState, setInstanceState } from "~/lib/instance";
import { cookie } from "~/lib/request";
@@ -49,17 +55,40 @@ export const accept = async (instanceId: string, pubId: string) => {
);
evaluator.deadline = deadline;
await setInstanceState(instanceId, pubId, instanceState);
- // Unschedule reminder email.
+ // Unschedule reminder email to evaluator.
await unscheduleInvitationReminderEmail(instanceId, pubId, evaluator);
- // Unschedule no-reply notification email.
+ // Unschedule no-reply notification email to community manager.
await unscheduleNoReplyNotificationEmail(instanceId, pubId, evaluator);
- // Immediately send accepted notification email.
+ // Immediately send accepted notification email to community manager.
await sendAcceptedNotificationEmail(instanceId, instanceConfig, pubId, evaluator);
// Immediately send accepted email to evaluator.
await sendAcceptedEmail(instanceId, instanceConfig, pubId, evaluator);
-
- // Schedule no-submit notification email.
+ // Schedule no-submit notification email to community manager.
await scheduleNoSubmitNotificationEmail(instanceId, instanceConfig, pubId, evaluator);
+
+ // schedule prompt evaluation email to evaluator.
+ await schedulePromptEvalBonusReminderEmail(instanceId, instanceConfig, pubId, evaluator);
+ //schedule final prompt eval email to evaluator
+ await scheduleFinalPromptEvalBonusReminderEmail(
+ instanceId,
+ instanceConfig,
+ pubId,
+ evaluator
+ );
+ //schedule eval reminder email to evaluator
+ await scheduleEvaluationReminderEmail(instanceId, instanceConfig, pubId, evaluator);
+ //schedule final eval reminder email to evaluator
+ await scheduleFinalEvaluationReminderEmail(instanceId, instanceConfig, pubId, evaluator);
+ //schedule follow up to final eval reminder email to evaluator
+ await scheduleFollowUpToFinalEvaluationReminderEmail(
+ instanceId,
+ instanceConfig,
+ pubId,
+ evaluator
+ );
+ // schedule no-submit notification email to evalutaor
+ await sendNoticeOfNoSubmitEmail(instanceId, instanceConfig, pubId, evaluator);
+
return { success: true };
} catch (error) {
return { error: error.message };
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index 48efe69cec..c471845715 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -5,6 +5,7 @@ import {
EvaluatorWithInvite,
InstanceConfig,
} from "~/lib/types";
+import { SendEmailResponseBody } from "../../../packages/contracts";
const DAYS_TO_ACCEPT_INVITE = 10;
const DAYS_TO_REMIND_EVALUATOR = 5;
@@ -53,6 +54,42 @@ const makeNoReplyJobKey = (instanceId: string, pubId: string, evaluator: Evaluat
const makeNoSubmitJobKey = (instanceId: string, pubId: string, evaluator: EvaluatorWithInvite) =>
`send-email-${instanceId}-${pubId}-${evaluator.userId}-no-submit`;
+const makePromptEvalBonusReminderJobKey = (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => `send-email-${instanceId}-${pubId}-${evaluator.userId}-prompt-eval-bonus-reminder`;
+
+const makeFinalPromptEvalBonusReminderJobKey = (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => `send-email-${instanceId}-${pubId}-${evaluator.userId}-final-prompt-eval-bonus-reminder`;
+
+const makeEvalReminderJobKey = (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => `send-email-${instanceId}-${pubId}-${evaluator.userId}-eval-reminder`;
+
+const makeFinalEvalReminderJobKey = (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => `send-email-${instanceId}-${pubId}-${evaluator.userId}-final-eval-reminder`;
+
+const makeFollowUpToFinalEvalReminderJobKey = (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => `send-email-${instanceId}-${pubId}-${evaluator.userId}-follow-up-to-final-eval-reminder`;
+
+const makeNoticeOfNoSubmitJobKey = (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => `send-email-${instanceId}-${pubId}-${evaluator.userId}-no-submit-notice`;
+
// sent to the community manager
export const scheduleNoReplyNotificationEmail = async (
instanceId: string,
@@ -397,7 +434,7 @@ export const sendAcceptedEmail = async (
};
// Send prompt evaluation bonus reminder email
-export const sendPromptEvalBonusReminderEmail = async (
+export const schedulePromptEvalBonusReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
@@ -440,7 +477,7 @@ export const sendPromptEvalBonusReminderEmail = async (
};
// Send final prompt evaluation bonus reminder email
-export const sendFinalPromptEvalBonusReminderEmail = async (
+export const scheduleFinalPromptEvalBonusReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
@@ -480,7 +517,7 @@ export const sendFinalPromptEvalBonusReminderEmail = async (
};
// Send evaluation reminder email
-export const sendEvaluationReminderEmail = async (
+export const scheduleEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
@@ -521,7 +558,7 @@ export const sendEvaluationReminderEmail = async (
};
// Send final evaluation reminder email
-export const sendFinalEvaluationReminderEmail = async (
+export const scheduleFinalEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
@@ -555,7 +592,7 @@ export const sendFinalEvaluationReminderEmail = async (
};
// Send follow-up to evaluation reminder email
-export const sendFollowUpToFinalEvaluationReminderEmail = async (
+export const scheduleFollowUpToFinalEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
pubId: string,
@@ -629,3 +666,19 @@ export const sendNoticeOfNoSubmitEmail = async (
},
});
};
+// unschedules all the deadline reminder emails
+export const unscheduleAllDeadlineReminderEmails = async (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWhoAccepted
+) => {
+ const jobKeys = [
+ makePromptEvalBonusReminderJobKey(instanceId, pubId, evaluator),
+ makeFinalPromptEvalBonusReminderJobKey(instanceId, pubId, evaluator),
+ makeEvalReminderJobKey(instanceId, pubId, evaluator),
+ makeFinalEvalReminderJobKey(instanceId, pubId, evaluator),
+ makeFollowUpToFinalEvalReminderJobKey(instanceId, pubId, evaluator),
+ makeNoticeOfNoSubmitJobKey(instanceId, pubId, evaluator),
+ ];
+ return Promise.all(jobKeys.map((jobKey) => client.unscheduleEmail(instanceId, jobKey)));
+};
diff --git a/packages/sdk/src/client.ts b/packages/sdk/src/client.ts
index 622ac58e19..4049295f25 100644
--- a/packages/sdk/src/client.ts
+++ b/packages/sdk/src/client.ts
@@ -9,7 +9,6 @@ import {
ScheduleEmailResponseBody,
SendEmailRequestBody,
SendEmailResponseBody,
- UpdatePubRequestBody,
UpdatePubResponseBody,
User,
api,
From 86951904c9ea8236abd16174d2dd2ddf242bc68d Mon Sep 17 00:00:00 2001
From: qweliant
Date: Thu, 15 Feb 2024 15:50:38 -0500
Subject: [PATCH 05/10] add run key
---
integrations/evaluations/lib/emails.ts | 115 ++++++++++++++++++-------
1 file changed, 83 insertions(+), 32 deletions(-)
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index c471845715..9ba01f0a90 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -5,7 +5,6 @@ import {
EvaluatorWithInvite,
InstanceConfig,
} from "~/lib/types";
-import { SendEmailResponseBody } from "../../../packages/contracts";
const DAYS_TO_ACCEPT_INVITE = 10;
const DAYS_TO_REMIND_EVALUATOR = 5;
@@ -287,8 +286,7 @@ ${notificationFooter}`,
});
};
-// sent to the evaluator
-
+// emails sent to the evaluator
/**
*
* Sends an email to the evaluator with the invitation to evaluate the pub.
@@ -325,7 +323,7 @@ export const sendInviteEmail = async (
};
/**
- * Sends an email to the evaluator as a reminder to accept the invitation to evaluate the pub.
+ * Schedules an email to the evaluator as a reminder to accept the invitation to evaluate the pub.
* @param instanceId
* @param instanceConfig
* @param pubId
@@ -433,7 +431,14 @@ export const sendAcceptedEmail = async (
});
};
-// Send prompt evaluation bonus reminder email
+/**
+ * Schedules a reminder email to an evaluator for prompt evaluation bonus.
+ * @param instanceId - The ID of the instance.
+ * @param instanceConfig - The configuration of the instance.
+ * @param pubId - The ID of the publication.
+ * @param evaluator - The evaluator who accepted the evaluation.
+ * @returns A promise that resolves when the email is sent.
+ */
export const schedulePromptEvalBonusReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -441,42 +446,51 @@ export const schedulePromptEvalBonusReminderEmail = async (
evaluator: EvaluatorWhoAccepted
) => {
const deadline = getDeadline(instanceConfig, evaluator);
- const reminderDeadline = new Date(deadline.getTime() - 14 * (1000 * 60 * 60 * 24));
- return client.sendEmail(instanceId, {
- to: {
- userId: evaluator.userId,
- },
- subject: `[Unjournal] Reminder to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" for prompt evaluation bonus`,
- message: `Hi {{user.firstName}},
+ const reminderDeadline = new Date(deadline.getTime() - 21 * (1000 * 60 * 60 * 24));
+ const jobKey = makePromptEvalBonusReminderJobKey(instanceId, pubId, evaluator);
+ const runAt = reminderDeadline;
+ return client.scheduleEmail(
+ instanceId,
+ {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Reminder to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" for prompt evaluation bonus`,
+ message: `Hi {{user.firstName}},
Thanks again for agreeing to evaluate "{{pubs.submission.values["${
instanceConfig.titleFieldSlug
}"]}}" for The Unjournal.
- This note is a reminder to submit your evaluation by ${new Date(
- reminderDeadline.getTime() - 14 * (1000 * 60 * 60 * 24)
- ).toLocaleDateString()} to receive a $100 “prompt evaluation bonus,” in addition to your baseline compensation. Please note that after ${new Date(
- deadline.getTime()
- ).toLocaleDateString()} we will consider re-assigning the evaluation, and later submissions may not be eligible for the full baseline compensation.
+ This note is a reminder to submit your evaluation by ${reminderDeadline.toLocaleDateString()} to receive a $100 “prompt evaluation bonus,” in addition to your baseline compensation. Please note that after ${deadline.toLocaleDateString()} we will consider re-assigning the evaluation, and later submissions may not be eligible for the full baseline compensation.
Please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.
Thanks and best wishes,
{{users.invitor.firstName}} {{users.invitor.lastName}}
Unjournal.org
`,
- include: {
- pubs: {
- submission: pubId,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
},
- users: {
- invitor: evaluator.invitedBy,
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
},
- extra: {
- evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
- },
- });
+ { jobKey, runAt }
+ );
};
-// Send final prompt evaluation bonus reminder email
+/**
+ * Schedules a final reminder email to an evaluator for prompt evaluation bonus.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const scheduleFinalPromptEvalBonusReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -516,7 +530,14 @@ export const scheduleFinalPromptEvalBonusReminderEmail = async (
});
};
-// Send evaluation reminder email
+/**
+ * Schedules a reminder email to an evaluator to submit their evaluation.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const scheduleEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -557,7 +578,14 @@ export const scheduleEvaluationReminderEmail = async (
});
};
-// Send final evaluation reminder email
+/**
+ * Schedules a final reminder email to an evaluator to submit their evaluation.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const scheduleFinalEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -591,7 +619,14 @@ export const scheduleFinalEvaluationReminderEmail = async (
});
};
-// Send follow-up to evaluation reminder email
+/**
+ * Schedules a follow-up to evaluation reminder email to an evaluator.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const scheduleFollowUpToFinalEvaluationReminderEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -629,7 +664,14 @@ export const scheduleFollowUpToFinalEvaluationReminderEmail = async (
});
};
-// Send notice of no submit email
+/**
+ * Schedules a notice of no submit email to an evaluator.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const sendNoticeOfNoSubmitEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -666,7 +708,16 @@ export const sendNoticeOfNoSubmitEmail = async (
},
});
};
-// unschedules all the deadline reminder emails
+
+/**
+ * Unschedules all the deadline reminder emails.
+ * `client.unscheduleEmail()` returns no-op for emails that have been
+ * sent, allowing us to call it without checking if an error
+ * @param instanceId
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const unscheduleAllDeadlineReminderEmails = async (
instanceId: string,
pubId: string,
From 073580f0ccd4596d61160a54c416d4634ab0cd17 Mon Sep 17 00:00:00 2001
From: qweliant
Date: Thu, 15 Feb 2024 18:33:43 -0500
Subject: [PATCH 06/10] add job keys and runAts
---
integrations/evaluations/lib/emails.ts | 191 ++++++++++++++-----------
1 file changed, 111 insertions(+), 80 deletions(-)
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index 9ba01f0a90..37ec5acafb 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -460,7 +460,9 @@ export const schedulePromptEvalBonusReminderEmail = async (
Thanks again for agreeing to evaluate "{{pubs.submission.values["${
instanceConfig.titleFieldSlug
}"]}}" for The Unjournal.
- This note is a reminder to submit your evaluation by ${reminderDeadline.toLocaleDateString()} to receive a $100 “prompt evaluation bonus,” in addition to your baseline compensation. Please note that after ${deadline.toLocaleDateString()} we will consider re-assigning the evaluation, and later submissions may not be eligible for the full baseline compensation.
+ This note is a reminder to submit your evaluation by ${reminderDeadline.toLocaleDateString()} to receive a $100 “prompt evaluation bonus,” in addition to your baseline compensation. Please note that after ${new Date(
+ deadline
+ ).toLocaleDateString()} we will consider re-assigning the evaluation, and later submissions may not be eligible for the full baseline compensation.
Please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.
@@ -499,35 +501,39 @@ export const scheduleFinalPromptEvalBonusReminderEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const reminderDeadline = new Date(deadline.getTime() - 14 * (1000 * 60 * 60 * 24));
- return client.sendEmail(instanceId, {
- to: {
- userId: evaluator.userId,
- },
- subject: `[Unjournal] Final Reminder: Submit evaluation for prompt bonus "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
- message: `Hi {{user.firstName}},
+ const jobKey = makeFinalPromptEvalBonusReminderJobKey(instanceId, pubId, evaluator);
+ const runAt = reminderDeadline;
+ return client.scheduleEmail(
+ instanceId,
+ {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Final Reminder: Submit evaluation for prompt bonus "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `Hi {{user.firstName}},
This is a final reminder to submit your evaluation for "{{pubs.submission.values["${
instanceConfig.titleFieldSlug
- }"]}}" by the deadline ${new Date(
- reminderDeadline.getTime()
- ).toLocaleDateString()} to receive the $100 “prompt evaluation bonus.”
+ }"]}}" by the deadline ${reminderDeadline.toLocaleDateString()} to receive the $100 “prompt evaluation bonus.”
If you haven't already, please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
Once your evaluation has been submitted and reviewed, we will follow up with details about payment and next steps.
Thanks and best wishes,
{{users.invitor.firstName}} {{users.invitor.lastName}}
Unjournal.org
`,
- include: {
- pubs: {
- submission: pubId,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
},
- users: {
- invitor: evaluator.invitedBy,
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
},
- extra: {
- evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
- },
- });
+ { jobKey, runAt }
+ );
};
/**
@@ -545,13 +551,17 @@ export const scheduleEvaluationReminderEmail = async (
evaluator: EvaluatorWhoAccepted
) => {
const deadline = getDeadline(instanceConfig, evaluator);
+ const jobKey = makeEvalReminderJobKey(instanceId, pubId, evaluator);
+ const runAt = new Date(deadline.getTime() - 7 * (1000 * 60 * 60 * 24));
- return client.sendEmail(instanceId, {
- to: {
- userId: evaluator.userId,
- },
- subject: `[Unjournal] Reminder to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" by next week`,
- message: `Hi {{user.firstName}},
+ return client.scheduleEmail(
+ instanceId,
+ {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Reminder to evaluate "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" by next week`,
+ message: `Hi {{user.firstName}},
Thank you again for agreeing to evaluate "{{pubs.submission.values["${
instanceConfig.titleFieldSlug
}"]}}" for The Unjournal.
@@ -564,18 +574,20 @@ export const scheduleEvaluationReminderEmail = async (
Thanks and best wishes,
{{users.invitor.firstName}} {{users.invitor.lastName}}
Unjournal.org
`,
- include: {
- pubs: {
- submission: pubId,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
},
- users: {
- invitor: evaluator.invitedBy,
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
},
- extra: {
- evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
- },
- });
+ { jobKey, runAt }
+ );
};
/**
@@ -592,12 +604,17 @@ export const scheduleFinalEvaluationReminderEmail = async (
pubId: string,
evaluator: EvaluatorWhoAccepted
) => {
- return client.sendEmail(instanceId, {
- to: {
- userId: evaluator.userId,
- },
- subject: `[Unjournal] Final Reminder: Evaluation due tomorrow`,
- message: `Hi {{user.firstName}},
+ const deadline = getDeadline(instanceConfig, evaluator);
+ const jobKey = makeFinalEvalReminderJobKey(instanceId, pubId, evaluator);
+ const runAt = new Date(deadline.getTime() - 1 * (1000 * 60 * 60 * 24));
+ return client.scheduleEmail(
+ instanceId,
+ {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Final Reminder: Evaluation due tomorrow`,
+ message: `Hi {{user.firstName}},
This note is a final reminder that your evaluation for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}" is due tomorrow. Please make sure to submit your evaluation by the deadline.
If you haven't already, please submit your evaluation and rating, as well as any specific considerations, using this evaluation form. The form includes instructions and information about the paper/project.
If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
@@ -605,18 +622,20 @@ export const scheduleFinalEvaluationReminderEmail = async (
Thanks and best wishes,
{{users.invitor.firstName}} {{users.invitor.lastName}}
Unjournal.org
`,
- include: {
- pubs: {
- submission: pubId,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
},
- users: {
- invitor: evaluator.invitedBy,
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
},
- extra: {
- evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
- },
- });
+ { jobKey, runAt }
+ );
};
/**
@@ -634,34 +653,40 @@ export const scheduleFollowUpToFinalEvaluationReminderEmail = async (
evaluator: EvaluatorWhoAccepted
) => {
const deadline = getDeadline(instanceConfig, evaluator);
- return client.sendEmail(instanceId, {
- to: {
- userId: evaluator.userId,
- },
- subject: `[Unjournal] Follow-up: Evaluation overdue, to be reassigned`,
- message: `Hi {{user.firstName}},
+ const jobKey = makeFollowUpToFinalEvalReminderJobKey(instanceId, pubId, evaluator);
+ const runAt = new Date(deadline.getTime() + 6 * (1000 * 60 * 60 * 24));
+ return client.scheduleEmail(
+ instanceId,
+ {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Follow-up: Evaluation overdue, to be reassigned`,
+ message: `Hi {{user.firstName}},
This note is a reminder that your evaluation for "{{pubs.submission.values["${
instanceConfig.titleFieldSlug
}"]}}" is overdue. We are now planning to reassign the evaluation to another evaluator.
If you have completed the evaluation but forgot to submit it, please submit your evaluation and rating today using this evaluation form. If we don't hear from you by the end of ${new Date(
- deadline.getTime()
+ deadline.getTime() + 7 * (1000 * 60 * 60 * 24)
).toLocaleDateString()}, we will remove you from this assignment and you will no longer be eligible for compensation.
If you have any questions, do not hesitate to reach out to me at {{users.invitor.email}}.
Thanks and best wishes,
{{users.invitor.firstName}} {{users.invitor.lastName}}
Unjournal.org
`,
- include: {
- pubs: {
- submission: pubId,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
},
- users: {
- invitor: evaluator.invitedBy,
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
},
- extra: {
- evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
- },
- });
+ { jobKey, runAt }
+ );
};
/**
@@ -679,12 +704,16 @@ export const sendNoticeOfNoSubmitEmail = async (
evaluator: EvaluatorWhoAccepted
) => {
const deadline = getDeadline(instanceConfig, evaluator);
- return client.sendEmail(instanceId, {
- to: {
- userId: evaluator.userId,
- },
- subject: `[Unjournal] Evaluation not submitted for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
- message: `Hi {{user.firstName}},
+ const jobKey = makeNoticeOfNoSubmitJobKey(instanceId, pubId, evaluator);
+ const runAt = new Date(deadline.getTime() + 8 * (1000 * 60 * 60 * 24));
+ return client.scheduleEmail(
+ instanceId,
+ {
+ to: {
+ userId: evaluator.userId,
+ },
+ subject: `[Unjournal] Evaluation not submitted for "{{pubs.submission.values["${instanceConfig.titleFieldSlug}"]}}"`,
+ message: `Hi {{user.firstName}},
This is to inform you that you have not submitted an evaluation for "{{pubs.submission.values["${
instanceConfig.titleFieldSlug
}"]}}", which was due on ${new Date(deadline.getTime()).toLocaleDateString()}.
@@ -695,18 +724,20 @@ export const sendNoticeOfNoSubmitEmail = async (
Thanks and best wishes,
{{users.invitor.firstName}} {{users.invitor.lastName}}
Unjournal.org
`,
- include: {
- pubs: {
- submission: pubId,
+ include: {
+ pubs: {
+ submission: pubId,
+ },
+ users: {
+ invitor: evaluator.invitedBy,
+ },
},
- users: {
- invitor: evaluator.invitedBy,
+ extra: {
+ evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
},
},
- extra: {
- evaluate_link: `{{instance.actions.evaluate}}?instanceId={{instance.id}}&pubId={{pubs.submission.id}}&token={{user.token}}`,
- },
- });
+ { jobKey, runAt }
+ );
};
/**
From fad7445f3e3ba43fb99868ca10b0d4d3a7af8593 Mon Sep 17 00:00:00 2001
From: qweliant
Date: Tue, 20 Feb 2024 09:52:30 -0500
Subject: [PATCH 07/10] test emails
---
integrations/evaluations/lib/emails.ts | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index 37ec5acafb..d7e28acd23 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -448,7 +448,8 @@ export const schedulePromptEvalBonusReminderEmail = async (
const deadline = getDeadline(instanceConfig, evaluator);
const reminderDeadline = new Date(deadline.getTime() - 21 * (1000 * 60 * 60 * 24));
const jobKey = makePromptEvalBonusReminderJobKey(instanceId, pubId, evaluator);
- const runAt = reminderDeadline;
+ // const runAt = reminderDeadline;
+ const runAt = new Date(Date.now());
return client.scheduleEmail(
instanceId,
{
@@ -502,7 +503,9 @@ export const scheduleFinalPromptEvalBonusReminderEmail = async (
const deadline = getDeadline(instanceConfig, evaluator);
const reminderDeadline = new Date(deadline.getTime() - 14 * (1000 * 60 * 60 * 24));
const jobKey = makeFinalPromptEvalBonusReminderJobKey(instanceId, pubId, evaluator);
- const runAt = reminderDeadline;
+ // const runAt = reminderDeadline;
+ const runAt = new Date(Date.now());
+
return client.scheduleEmail(
instanceId,
{
@@ -552,7 +555,8 @@ export const scheduleEvaluationReminderEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeEvalReminderJobKey(instanceId, pubId, evaluator);
- const runAt = new Date(deadline.getTime() - 7 * (1000 * 60 * 60 * 24));
+ // const runAt = new Date(deadline.getTime() - 7 * (1000 * 60 * 60 * 24));
+ const runAt = new Date(Date.now());
return client.scheduleEmail(
instanceId,
@@ -606,7 +610,9 @@ export const scheduleFinalEvaluationReminderEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeFinalEvalReminderJobKey(instanceId, pubId, evaluator);
- const runAt = new Date(deadline.getTime() - 1 * (1000 * 60 * 60 * 24));
+ // const runAt = new Date(deadline.getTime() - 1 * (1000 * 60 * 60 * 24));
+ const runAt = new Date(Date.now());
+
return client.scheduleEmail(
instanceId,
{
@@ -654,7 +660,9 @@ export const scheduleFollowUpToFinalEvaluationReminderEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeFollowUpToFinalEvalReminderJobKey(instanceId, pubId, evaluator);
- const runAt = new Date(deadline.getTime() + 6 * (1000 * 60 * 60 * 24));
+ // const runAt = new Date(deadline.getTime() + 6 * (1000 * 60 * 60 * 24));
+ const runAt = new Date(Date.now());
+
return client.scheduleEmail(
instanceId,
{
@@ -705,7 +713,9 @@ export const sendNoticeOfNoSubmitEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeNoticeOfNoSubmitJobKey(instanceId, pubId, evaluator);
- const runAt = new Date(deadline.getTime() + 8 * (1000 * 60 * 60 * 24));
+ // const runAt = new Date(deadline.getTime() + 8 * (1000 * 60 * 60 * 24));
+ const runAt = new Date(Date.now());
+
return client.scheduleEmail(
instanceId,
{
From c077d6a1d02a722d5bbca6db33243ed4ac7135ea Mon Sep 17 00:00:00 2001
From: qweliant
Date: Tue, 27 Feb 2024 15:40:10 -0500
Subject: [PATCH 08/10] rmv date.now add JSdoc for emails bc it helps
diferentiate them
---
integrations/evaluations/lib/emails.ts | 79 ++++++++++++++++++++++----
1 file changed, 68 insertions(+), 11 deletions(-)
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index d7e28acd23..c103faabb7 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -89,7 +89,15 @@ const makeNoticeOfNoSubmitJobKey = (
evaluator: EvaluatorWhoAccepted
) => `send-email-${instanceId}-${pubId}-${evaluator.userId}-no-submit-notice`;
-// sent to the community manager
+// emails sent to the evaluation manager
+/**
+ * Schedules an email to the evaluation manager to notify them that an invited evaluator has not responded to the invitation.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const scheduleNoReplyNotificationEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -126,6 +134,13 @@ ${notificationFooter}`,
);
};
+/**
+ * Unschedules the no reply notification email for the evaluation manager.
+ * @param instanceId
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const unscheduleNoReplyNotificationEmail = (
instanceId: string,
pubId: string,
@@ -135,6 +150,14 @@ export const unscheduleNoReplyNotificationEmail = (
return client.unscheduleEmail(instanceId, jobKey);
};
+/**
+ * Schedules an email to the evaluation manager to notify them that an evaluator has not submitted their evaluation.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const scheduleNoSubmitNotificationEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -171,6 +194,13 @@ ${notificationFooter}`,
);
};
+/**
+ * Unschedules the no submit notification email for the evaluation manager.
+ * @param instanceId
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const unscheduleNoSubmitNotificationEmail = (
instanceId: string,
pubId: string,
@@ -180,6 +210,14 @@ export const unscheduleNoSubmitNotificationEmail = (
return client.unscheduleEmail(instanceId, jobKey);
};
+/**
+ * Sends an email to the evaluation manager to notify them that an evaluator has requested more information.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const sendRequestedInfoNotification = (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -204,6 +242,14 @@ ${notificationFooter}`,
});
};
+/**
+ * Sends an email to the evaluation manager to notify them that an evaluator has accepted the invitation to evaluate the pub.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const sendAcceptedNotificationEmail = (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -231,6 +277,14 @@ ${notificationFooter}`,
});
};
+/**
+ * Sends an email to the evaluation manager to notify them that an evaluator has declined the invitation to evaluate the pub.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const sendDeclinedNotificationEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -258,6 +312,14 @@ ${notificationFooter}`,
});
};
+/**
+ * Sends an email to the evaluation manager to notify them that an evaluator has submitted their evaluation.
+ * @param instanceId
+ * @param instanceConfig
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
export const sendSubmittedNotificationEmail = async (
instanceId: string,
instanceConfig: InstanceConfig,
@@ -503,8 +565,7 @@ export const scheduleFinalPromptEvalBonusReminderEmail = async (
const deadline = getDeadline(instanceConfig, evaluator);
const reminderDeadline = new Date(deadline.getTime() - 14 * (1000 * 60 * 60 * 24));
const jobKey = makeFinalPromptEvalBonusReminderJobKey(instanceId, pubId, evaluator);
- // const runAt = reminderDeadline;
- const runAt = new Date(Date.now());
+ const runAt = reminderDeadline;
return client.scheduleEmail(
instanceId,
@@ -555,8 +616,7 @@ export const scheduleEvaluationReminderEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeEvalReminderJobKey(instanceId, pubId, evaluator);
- // const runAt = new Date(deadline.getTime() - 7 * (1000 * 60 * 60 * 24));
- const runAt = new Date(Date.now());
+ const runAt = new Date(deadline.getTime() - 7 * (1000 * 60 * 60 * 24));
return client.scheduleEmail(
instanceId,
@@ -610,8 +670,7 @@ export const scheduleFinalEvaluationReminderEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeFinalEvalReminderJobKey(instanceId, pubId, evaluator);
- // const runAt = new Date(deadline.getTime() - 1 * (1000 * 60 * 60 * 24));
- const runAt = new Date(Date.now());
+ const runAt = new Date(deadline.getTime() - 1 * (1000 * 60 * 60 * 24));
return client.scheduleEmail(
instanceId,
@@ -660,8 +719,7 @@ export const scheduleFollowUpToFinalEvaluationReminderEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeFollowUpToFinalEvalReminderJobKey(instanceId, pubId, evaluator);
- // const runAt = new Date(deadline.getTime() + 6 * (1000 * 60 * 60 * 24));
- const runAt = new Date(Date.now());
+ const runAt = new Date(deadline.getTime() + 6 * (1000 * 60 * 60 * 24));
return client.scheduleEmail(
instanceId,
@@ -713,8 +771,7 @@ export const sendNoticeOfNoSubmitEmail = async (
) => {
const deadline = getDeadline(instanceConfig, evaluator);
const jobKey = makeNoticeOfNoSubmitJobKey(instanceId, pubId, evaluator);
- // const runAt = new Date(deadline.getTime() + 8 * (1000 * 60 * 60 * 24));
- const runAt = new Date(Date.now());
+ const runAt = new Date(deadline.getTime() + 8 * (1000 * 60 * 60 * 24));
return client.scheduleEmail(
instanceId,
From dace64e258856f6de01b4d3a04af662f7d2fe977 Mon Sep 17 00:00:00 2001
From: qweliant
Date: Tue, 27 Feb 2024 16:55:42 -0500
Subject: [PATCH 09/10] unschedule on evaluator
---
.../evaluations/app/actions/manage/actions.ts | 13 +++++++++---
integrations/evaluations/lib/emails.ts | 20 +++++++++++++++++++
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/integrations/evaluations/app/actions/manage/actions.ts b/integrations/evaluations/app/actions/manage/actions.ts
index 08978cd164..79f5624c0b 100644
--- a/integrations/evaluations/app/actions/manage/actions.ts
+++ b/integrations/evaluations/app/actions/manage/actions.ts
@@ -6,12 +6,14 @@ import { expect } from "utils";
import { getInstanceConfig, getInstanceState, setInstanceState } from "~/lib/instance";
import { client } from "~/lib/pubpub";
import { cookie } from "~/lib/request";
-import { isInvited } from "~/lib/types";
+import { EvaluatorWhoAccepted, EvaluatorWithInvite, isInvited } from "~/lib/types";
import {
- scheduleNoReplyNotificationEmail,
scheduleInvitationReminderEmail,
+ scheduleNoReplyNotificationEmail,
sendInviteEmail,
-} from "../../../lib/emails";
+ unscheduleAllDeadlineReminderEmails,
+ unscheduleAllManagerEmails,
+} from "~/lib/emails";
import { InviteFormEvaluator } from "./types";
export const save = async (
@@ -118,6 +120,10 @@ export const remove = async (instanceId: string, pubId: string, userId: string)
const evaluation = pub.children.find(
(child) => child.values[instanceConfig.evaluatorFieldSlug] === userId
);
+ await unscheduleAllDeadlineReminderEmails(instanceId, pubId, {
+ userId,
+ } as EvaluatorWhoAccepted);
+ await unscheduleAllManagerEmails(instanceId, pubId, { userId } as EvaluatorWithInvite);
// TODO: When an evaluator is removed, we should unschedule reminder
// email and notification email(s).
if (evaluation !== undefined) {
@@ -127,6 +133,7 @@ export const remove = async (instanceId: string, pubId: string, userId: string)
delete instanceState[userId];
await setInstanceState(instanceId, pubId, instanceState);
}
+
return { success: true };
} catch (error) {
return { error: error.message };
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index c103faabb7..cd4d6a4f67 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -831,3 +831,23 @@ export const unscheduleAllDeadlineReminderEmails = async (
];
return Promise.all(jobKeys.map((jobKey) => client.unscheduleEmail(instanceId, jobKey)));
};
+
+/**
+ * Unschedules all emails.
+ * @param instanceId
+ * @param pubId
+ * @param evaluator
+ * @returns
+ */
+export const unscheduleAllManagerEmails = async (
+ instanceId: string,
+ pubId: string,
+ evaluator: EvaluatorWithInvite
+) => {
+ const jobKeys = [
+ makeReminderJobKey(instanceId, pubId, evaluator),
+ makeNoReplyJobKey(instanceId, pubId, evaluator),
+ makeNoSubmitJobKey(instanceId, pubId, evaluator),
+ ];
+ return Promise.all(jobKeys.map((jobKey) => client.unscheduleEmail(instanceId, jobKey)));
+}
\ No newline at end of file
From bfacd4199e2a07ee48638cf6c906f41a40ec43af Mon Sep 17 00:00:00 2001
From: qweliant
Date: Wed, 28 Feb 2024 09:52:41 -0500
Subject: [PATCH 10/10] rmv test, use instanace stae for evaluator
---
.../evaluations/app/actions/manage/actions.ts | 22 +++++++++++++------
integrations/evaluations/lib/emails.ts | 8 +++----
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/integrations/evaluations/app/actions/manage/actions.ts b/integrations/evaluations/app/actions/manage/actions.ts
index 79f5624c0b..89d7bd1416 100644
--- a/integrations/evaluations/app/actions/manage/actions.ts
+++ b/integrations/evaluations/app/actions/manage/actions.ts
@@ -6,7 +6,13 @@ import { expect } from "utils";
import { getInstanceConfig, getInstanceState, setInstanceState } from "~/lib/instance";
import { client } from "~/lib/pubpub";
import { cookie } from "~/lib/request";
-import { EvaluatorWhoAccepted, EvaluatorWithInvite, isInvited } from "~/lib/types";
+import {
+ EvaluatorWhoAccepted,
+ EvaluatorWithInvite,
+ assertHasAccepted,
+ assertIsInvited,
+ isInvited,
+} from "~/lib/types";
import {
scheduleInvitationReminderEmail,
scheduleNoReplyNotificationEmail,
@@ -120,16 +126,18 @@ export const remove = async (instanceId: string, pubId: string, userId: string)
const evaluation = pub.children.find(
(child) => child.values[instanceConfig.evaluatorFieldSlug] === userId
);
- await unscheduleAllDeadlineReminderEmails(instanceId, pubId, {
- userId,
- } as EvaluatorWhoAccepted);
- await unscheduleAllManagerEmails(instanceId, pubId, { userId } as EvaluatorWithInvite);
- // TODO: When an evaluator is removed, we should unschedule reminder
- // email and notification email(s).
+
if (evaluation !== undefined) {
await client.deletePub(instanceId, evaluation.id);
}
if (instanceState !== undefined) {
+ let evaluator = expect(
+ instanceState[userId],
+ `User was not invited to evaluate pub ${pubId}`
+ );
+ assertHasAccepted(evaluator);
+ await unscheduleAllDeadlineReminderEmails(instanceId, pubId, evaluator);
+ await unscheduleAllManagerEmails(instanceId, pubId, evaluator);
delete instanceState[userId];
await setInstanceState(instanceId, pubId, instanceState);
}
diff --git a/integrations/evaluations/lib/emails.ts b/integrations/evaluations/lib/emails.ts
index cd4d6a4f67..57d3243014 100644
--- a/integrations/evaluations/lib/emails.ts
+++ b/integrations/evaluations/lib/emails.ts
@@ -510,8 +510,8 @@ export const schedulePromptEvalBonusReminderEmail = async (
const deadline = getDeadline(instanceConfig, evaluator);
const reminderDeadline = new Date(deadline.getTime() - 21 * (1000 * 60 * 60 * 24));
const jobKey = makePromptEvalBonusReminderJobKey(instanceId, pubId, evaluator);
- // const runAt = reminderDeadline;
- const runAt = new Date(Date.now());
+ const runAt = reminderDeadline;
+
return client.scheduleEmail(
instanceId,
{
@@ -833,7 +833,7 @@ export const unscheduleAllDeadlineReminderEmails = async (
};
/**
- * Unschedules all emails.
+ * Unschedules all emails.
* @param instanceId
* @param pubId
* @param evaluator
@@ -850,4 +850,4 @@ export const unscheduleAllManagerEmails = async (
makeNoSubmitJobKey(instanceId, pubId, evaluator),
];
return Promise.all(jobKeys.map((jobKey) => client.unscheduleEmail(instanceId, jobKey)));
-}
\ No newline at end of file
+};