Track open rate for new post notifications (user clicked the button in the link or not). No data about the user is collected during the process, it only uses an ID inserted by the issue delivery worker.
147 lines
3.3 KiB
Rust
147 lines
3.3 KiB
Rust
use crate::{domain::PostEntry, routes::DashboardStats};
|
|
use askama::Template;
|
|
use uuid::Uuid;
|
|
|
|
#[derive(Template)]
|
|
pub enum MessageTemplate {
|
|
#[template(path = "../templates/success.html")]
|
|
Success { message: String },
|
|
#[template(path = "../templates/error.html")]
|
|
Error { message: String },
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "../templates/500.html")]
|
|
pub struct InternalErrorTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "../templates/login.html")]
|
|
pub struct LoginTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "../templates/dashboard.html")]
|
|
pub struct DashboardTemplate {
|
|
pub username: String,
|
|
pub idempotency_key_1: String,
|
|
pub idempotency_key_2: String,
|
|
pub stats: DashboardStats,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "home.html")]
|
|
pub struct HomeTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "posts.html")]
|
|
pub struct PostsTemplate {
|
|
pub posts: Vec<PostEntry>,
|
|
pub next_page: Option<i64>,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "posts.html", block = "posts")]
|
|
pub struct PostListTemplate {
|
|
pub posts: Vec<PostEntry>,
|
|
pub next_page: Option<i64>,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "post.html")]
|
|
pub struct PostTemplate {
|
|
pub post: PostEntry,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "confirm.html")]
|
|
pub struct ConfirmTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "404.html")]
|
|
pub struct NotFoundTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "unsubscribe_confirm.html")]
|
|
pub struct UnsubscribeConfirmTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "unsubscribe.html")]
|
|
pub struct UnsubscribeTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "email/new_post.html")]
|
|
pub struct NewPostEmailTemplate<'a> {
|
|
pub base_url: &'a str,
|
|
pub post_title: &'a str,
|
|
pub post_id: &'a Uuid,
|
|
pub post_excerpt: &'a str,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "email/standalone.html")]
|
|
pub struct StandaloneEmailTemplate<'a> {
|
|
pub base_url: &'a str,
|
|
pub html_content: &'a str,
|
|
pub text_content: &'a str,
|
|
}
|
|
|
|
pub trait EmailTemplate: Sync {
|
|
fn html(&self) -> String;
|
|
fn text(&self) -> String;
|
|
}
|
|
|
|
impl<'a> EmailTemplate for NewPostEmailTemplate<'a> {
|
|
fn html(&self) -> String {
|
|
self.render().unwrap()
|
|
}
|
|
|
|
fn text(&self) -> String {
|
|
format!(
|
|
r#"New post available!
|
|
|
|
Hello there!
|
|
I just published a new post that I think you'll find interesting:
|
|
|
|
"{}"
|
|
|
|
Read the full post: {}/posts/{}?origin=EMAIL_ID
|
|
|
|
This post covers practical insights and real-world examples that I hope will be valuable for your backend development journey.
|
|
|
|
Thanks for being a subscriber!
|
|
|
|
Best regards,
|
|
Alphonse
|
|
|
|
---
|
|
|
|
zero2prod - Building better backends with Rust
|
|
Visit the blog: {}
|
|
Unsubscribe: {}/unsubscribe/confirm?token=UNSUBSCRIBE_TOKEN
|
|
|
|
You're receiving this because you subscribed to the zero2prod newsletter."#,
|
|
self.post_title, self.base_url, self.post_id, self.base_url, self.base_url,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl<'a> EmailTemplate for StandaloneEmailTemplate<'a> {
|
|
fn html(&self) -> String {
|
|
self.render().unwrap()
|
|
}
|
|
|
|
fn text(&self) -> String {
|
|
format!(
|
|
r#"{}
|
|
|
|
---
|
|
|
|
zero2prod - Building better backends with Rust
|
|
Visit the blog: {}
|
|
Unsubscribe: {}/unsubscribe/confirm?token=UNSUBSCRIBE_TOKEN
|
|
|
|
You're receiving this because you subscribed to the zero2prod newsletter."#,
|
|
self.text_content, self.base_url, self.base_url
|
|
)
|
|
}
|
|
}
|