249 lines
5.9 KiB
Rust
249 lines
5.9 KiB
Rust
use crate::{
|
|
authentication::AuthenticatedUser,
|
|
domain::{CommentEntry, PostEntry, SubscriberEntry, UserEntry},
|
|
routes::{AppError, DashboardStats},
|
|
};
|
|
use askama::Template;
|
|
use axum::response::{Html, IntoResponse};
|
|
use uuid::Uuid;
|
|
|
|
pub struct HtmlTemplate<T>(pub T);
|
|
|
|
impl<T> IntoResponse for HtmlTemplate<T>
|
|
where
|
|
T: Template,
|
|
{
|
|
fn into_response(self) -> axum::response::Response {
|
|
match self.0.render() {
|
|
Ok(html) => Html(html).into_response(),
|
|
Err(err) => AppError::unexpected_page(anyhow::anyhow!(err)).into_response(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "user/profile.html")]
|
|
pub struct UserTemplate {
|
|
pub user: UserEntry,
|
|
pub session_username: Option<String>,
|
|
pub posts: Vec<PostEntry>,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "user/edit.html")]
|
|
pub struct UserEditTemplate {
|
|
pub user: UserEntry,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "message.html")]
|
|
pub struct MessageTemplate {
|
|
pub message: String,
|
|
pub error: bool,
|
|
}
|
|
|
|
impl MessageTemplate {
|
|
pub fn success(message: String) -> Self {
|
|
Self {
|
|
message,
|
|
error: false,
|
|
}
|
|
}
|
|
pub fn error(message: String) -> Self {
|
|
Self {
|
|
message,
|
|
error: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "../templates/login.html")]
|
|
pub struct LoginTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "dashboard/dashboard.html")]
|
|
pub struct DashboardTemplate {
|
|
pub user: AuthenticatedUser,
|
|
pub idempotency_key_1: String,
|
|
pub idempotency_key_2: String,
|
|
pub stats: DashboardStats,
|
|
pub subscribers: Vec<SubscriberEntry>,
|
|
pub current_page: i64,
|
|
pub max_page: i64,
|
|
pub count: i64,
|
|
pub users: Vec<UserEntry>,
|
|
pub posts: Vec<PostEntry>,
|
|
pub posts_current_page: i64,
|
|
pub posts_max_page: i64,
|
|
pub posts_count: i64,
|
|
pub comments: Vec<CommentEntry>,
|
|
pub comments_current_page: i64,
|
|
pub comments_max_page: i64,
|
|
pub comments_count: i64,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "dashboard/posts/list.html", block = "posts")]
|
|
pub struct PostsPageDashboardTemplate {
|
|
pub posts: Vec<PostEntry>,
|
|
pub posts_current_page: i64,
|
|
pub posts_max_page: i64,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "dashboard/comments/list.html", block = "comments")]
|
|
pub struct CommentsPageDashboardTemplate {
|
|
pub comments: Vec<CommentEntry>,
|
|
pub comments_current_page: i64,
|
|
pub comments_max_page: i64,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "home.html")]
|
|
pub struct HomeTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "posts/list.html")]
|
|
pub struct PostsTemplate {
|
|
pub posts: Vec<PostEntry>,
|
|
pub next_page: Option<i64>,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "posts/list.html", block = "posts")]
|
|
pub struct PostListTemplate {
|
|
pub posts: Vec<PostEntry>,
|
|
pub next_page: Option<i64>,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "posts/page.html")]
|
|
pub struct PostTemplate {
|
|
pub post: PostEntry,
|
|
pub post_html: String,
|
|
pub idempotency_key: String,
|
|
pub comments: Vec<CommentEntry>,
|
|
pub current_page: i64,
|
|
pub max_page: i64,
|
|
pub comments_count: i64,
|
|
pub session_user_id: Option<Uuid>,
|
|
pub session_username: Option<String>,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "posts/comments/list.html", block = "comments")]
|
|
pub struct CommentsList {
|
|
pub comments: Vec<CommentEntry>,
|
|
pub current_page: i64,
|
|
pub max_page: i64,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "dashboard/subscribers/list.html", block = "subs")]
|
|
pub struct SubListTemplate {
|
|
pub subscribers: Vec<SubscriberEntry>,
|
|
pub current_page: i64,
|
|
pub max_page: i64,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "subscribe/confirm.html")]
|
|
pub struct ConfirmTemplate;
|
|
|
|
#[derive(Template)]
|
|
pub enum ErrorTemplate {
|
|
#[template(path = "error/404.html")]
|
|
NotFound,
|
|
#[template(path = "error/500.html")]
|
|
InternalServer,
|
|
#[template(path = "error/403.html")]
|
|
Forbidden,
|
|
}
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "unsubscribe/confirm.html")]
|
|
pub struct UnsubscribeConfirmTemplate;
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "unsubscribe/form.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
|
|
)
|
|
}
|
|
}
|