Skip to content

Commit

Permalink
feature: made email templates html based and more stylized
Browse files Browse the repository at this point in the history
  • Loading branch information
cdxker committed Jan 6, 2025
1 parent 35fd66f commit 112d157
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 30 deletions.
5 changes: 4 additions & 1 deletion server/src/handlers/invitation_handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::auth_handler::AdminOnly;
use crate::{
data::models::{Invitation, OrganizationWithSubAndPlan, Pool, RedisPool},
data::models::{Invitation, OrganizationWithSubAndPlan, Pool, RedisPool, Templates},
errors::ServiceError,
middleware::auth_middleware::verify_admin,
operators::{
Expand Down Expand Up @@ -64,6 +64,7 @@ pub async fn post_invitation(
pool: web::Data<Pool>,
redis_pool: web::Data<RedisPool>,
org_with_plan_and_sub: OrganizationWithSubAndPlan,
templates: Templates<'_>,
user: AdminOnly,
) -> Result<HttpResponse, ServiceError> {
let invitation_data = invitation_data.into_inner();
Expand Down Expand Up @@ -119,6 +120,7 @@ pub async fn post_invitation(
send_invitation_for_existing_user(
email.clone(),
org_with_plan_and_sub.organization.name,
templates,
invitation_data.redirect_uri,
)
.await?;
Expand Down Expand Up @@ -152,6 +154,7 @@ pub async fn post_invitation(
send_invitation(
invitation.registration_url,
invitation.invitation,
templates,
org_with_plan_and_sub.organization.name,
)
.await?;
Expand Down
55 changes: 26 additions & 29 deletions server/src/operators/invitation_operator.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::email_operator::send_email;
use crate::data::models::{Invitation, Pool};
use crate::data::models::{Invitation, Pool, Templates};
use crate::errors::ServiceError;
use actix_web::web;
use diesel::prelude::*;
use diesel_async::RunQueryDsl;
use minijinja::context;

/// Diesel query
Expand Down Expand Up @@ -52,30 +53,28 @@ pub async fn get_invitation_by_id_query(
pub async fn send_invitation(
inv_url: String,
invitation: Invitation,
templates: Templates<'_>,
org_name: String,
) -> Result<(), ServiceError> {
let sg_email_content = format!(
"Hello,<br/><br/>
You have been invited to join the Trieve organization: <strong>{}</strong>.<br/><br/>
To get started, simply click <a href=\"{}\">here</a> or use the link below to register and activate your account:<br/>
<a href=\"{}\">{}</a><br/><br/>
We look forward to having you on board!<br/><br/>
Cheers,<br/>
The Trieve Team<br/>
<i>This email is intended for {}. If you encounter any issues or did not expect this invitation, please reach out to us directly at <a href=\"mailto:[email protected]\">[email protected]</a>.</i>",
org_name,
inv_url,
inv_url,
inv_url.split('?').collect::<Vec<&str>>().get(0).unwrap_or(&""),
invitation.email
);
let templ = templates.get_template("user_email_invite.html").unwrap();
let sg_email_content = templ
.render(context! {
org_name,
org_redirect_url => inv_url,
email => invitation.email,
new_user => true
})
.map_err(|e| {
ServiceError::InternalServerError(format!("Error rendering template {}", e))
})?;

send_email(sg_email_content, invitation.email, None)
}

pub async fn send_invitation_for_existing_user(
email: String,
org_name: String,
templates: Templates<'_>,
organization_url: String,
) -> Result<(), ServiceError> {
let split_org_url = organization_url.split('?').collect::<Vec<&str>>();
Expand All @@ -86,19 +85,17 @@ pub async fn send_invitation_for_existing_user(
split_org_url.get(1).unwrap_or(&"")
);

let sg_email_content = format!(
"You've been added to a Trieve organization: <b>{}</b>. <br/><br/>
To access this organization, simply click <a href=\"{}\">here</a> or use the link below:<br/>
<a href=\"{}\">{}</a><br/><br/>
Cheers,<br/>
The Trieve Team<br/>
<i>This email is intended for {}. If you encounter any issues or did not expect this invitation, please reach out to us directly at <a href=\"mailto:[email protected]\">[email protected]</a>.</i>",
org_name,
org_redirect_url,
org_redirect_url,
org_redirect_url,
email
);
let templ = templates.get_template("user_email_invite.html").unwrap();
let sg_email_content = templ
.render(context! {
org_name,
org_redirect_url,
email,
new_user => false,
})
.map_err(|e| {
ServiceError::InternalServerError(format!("Error rendering template {}", e))
})?;

send_email(sg_email_content, email, None)
}
Expand Down
84 changes: 84 additions & 0 deletions server/src/public/user_email_invite.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<!-- [Previous head section with styles remains the same] -->
<body style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">You've been invited to join an organization on Trieve!</span>
<!-- [Table structure remains the same until main content] -->
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;" valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding: 20px; background-color="#ffffff" " valign="top">
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
Hello!
</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
You've been invited to join on {{ org_name }} Trieve. Trieve is a powerful search and retrieval platform that helps teams collaborate and find information quickly.
</p>
{% if new_user %}
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
To get started, click the button below to register and activate your account:
</p>
{% else %}
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
To accept this invitation and join the organization, click the button below:
</p>
{% endif %}
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; box-sizing: border-box; width: 100%;" width="100%">
<tbody>
<tr>
<td align="left" style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;" valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
<tbody>
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; border-radius: 5px; text-align: center; background-color: #d946ef;" valign="top" align="center">
<a href="{{ org_redirect_url }}" target="_blank" style="border: solid 1px #d946ef; border-radius: 5px; box-sizing: border-box; cursor: pointer; display: inline-block; font-size: 14px; font-weight: bold; margin: 0; padding: 12px 25px; text-decoration: none; text-transform: capitalize; background-color: #d946ef; border-color: #d946ef; color: #ffffff;">Accept Invitation →</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>

<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
or if you prefer, click this link directly
</p>

<table role="presentation">
<tbody>
<tr>
<td align="left" style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;" valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
<tbody>
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; text-align: center;" valign="top" align="center">
<a href="{{ org_redirect_url }}" target="_blank"> {{ org_redirect_url }} </a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>

<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
If you have any questions about using Trieve, please don't hesitate to reach out to our support team.
</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
Best regards,<br/>
The Trieve Team
</p>
<hr style="border: 0; border-bottom: 1px solid #f6f6f6; margin: 20px 0;">
<p style="font-family: sans-serif; font-size: 12px; font-weight: normal; margin: 0; margin-bottom: 15px; color: #999999;">
This email is intended for {{ email }}. If you received this invitation in error or this email wasn't intended for you, please contact us at [email protected]. Please do not forward this email as the invitation link is unique to your email address.
</p>
</td>
</tr>
</table>
</td>
<!-- [Footer structure remains the same] -->
</body>
</html>

17 changes: 17 additions & 0 deletions server/static/output.css
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,10 @@ video {
display: flex;
}

.table {
display: table;
}

.hidden {
display: none;
}
Expand Down Expand Up @@ -705,6 +709,10 @@ video {
flex-shrink: 0;
}

.border-collapse {
border-collapse: collapse;
}

@keyframes pulse {
50% {
opacity: .5;
Expand Down Expand Up @@ -894,6 +902,10 @@ video {
font-weight: 500;
}

.capitalize {
text-transform: capitalize;
}

.tracking-tight {
letter-spacing: -0.025em;
}
Expand All @@ -917,6 +929,11 @@ video {
text-decoration-line: underline;
}

.antialiased {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.outline {
outline-style: solid;
}
Expand Down

0 comments on commit 112d157

Please sign in to comment.