2024-05-12 16:36:41 -04:00
|
|
|
use achubb_database::data::{article::Article, PsqlData};
|
2024-03-24 10:45:16 -04:00
|
|
|
use askama::Template;
|
2024-04-28 20:23:19 -04:00
|
|
|
use axum::{
|
|
|
|
|
extract::{Extension, Path},
|
|
|
|
|
response::IntoResponse,
|
|
|
|
|
routing::{get, Router},
|
|
|
|
|
};
|
|
|
|
|
use core::panic;
|
2024-05-11 09:32:29 -04:00
|
|
|
use sqlx::PgPool;
|
|
|
|
|
use std::{collections::HashMap, error::Error};
|
2024-04-28 20:23:19 -04:00
|
|
|
|
2024-05-17 14:55:30 -04:00
|
|
|
use super::{root::AppState, ArticleTemplate, HtmlTemplate, NavBar};
|
2024-03-24 10:45:16 -04:00
|
|
|
|
|
|
|
|
pub fn get_router() -> Router {
|
|
|
|
|
Router::new()
|
2024-05-11 07:53:20 -04:00
|
|
|
.route("/", get(blog))
|
2024-04-28 20:23:19 -04:00
|
|
|
.route("/:article", get(article))
|
2024-03-24 10:45:16 -04:00
|
|
|
}
|
|
|
|
|
|
2024-05-11 09:32:29 -04:00
|
|
|
async fn blog(state: Extension<AppState>) -> impl IntoResponse {
|
|
|
|
|
let db_pool = &state.db;
|
|
|
|
|
let list: Vec<String> = get_articles_as_links_list(db_pool)
|
|
|
|
|
.await
|
|
|
|
|
.expect("couldn't get articles");
|
2024-05-11 07:53:20 -04:00
|
|
|
let template = BlogTemplate {
|
|
|
|
|
active_navbar: NavBar::BLOG,
|
2024-05-11 09:32:29 -04:00
|
|
|
article_list: list.join("\n"),
|
2024-05-11 07:53:20 -04:00
|
|
|
};
|
|
|
|
|
HtmlTemplate(template)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Template)]
|
|
|
|
|
#[template(path = "blog.html")]
|
|
|
|
|
struct BlogTemplate {
|
|
|
|
|
active_navbar: &'static str,
|
2024-05-11 09:32:29 -04:00
|
|
|
article_list: String,
|
2024-05-11 07:53:20 -04:00
|
|
|
}
|
|
|
|
|
|
2024-03-24 10:45:16 -04:00
|
|
|
#[derive(Template)]
|
2024-05-17 14:55:30 -04:00
|
|
|
#[template(path = "blog_footer.html")]
|
|
|
|
|
struct BlogFooterTemplate {
|
2024-04-28 20:23:19 -04:00
|
|
|
previous: String,
|
2024-05-17 14:55:30 -04:00
|
|
|
next: String,
|
2024-03-24 10:45:16 -04:00
|
|
|
}
|
|
|
|
|
|
2024-04-28 20:23:19 -04:00
|
|
|
async fn article(
|
|
|
|
|
state: Extension<AppState>,
|
|
|
|
|
Path(params): Path<HashMap<String, String>>,
|
|
|
|
|
) -> impl IntoResponse {
|
|
|
|
|
let db_pool = &state.db;
|
|
|
|
|
let article_id: &String = params.get("article").unwrap();
|
|
|
|
|
let article: Article = match Article::read_by_reference(db_pool, article_id).await {
|
|
|
|
|
Ok(a) => *a,
|
|
|
|
|
Err(_) => panic!("Not an article at all!!!!"),
|
|
|
|
|
};
|
2024-05-17 14:55:30 -04:00
|
|
|
let footer = BlogFooterTemplate {
|
2024-04-28 20:23:19 -04:00
|
|
|
previous: match article.previous {
|
|
|
|
|
Some(a) => a,
|
|
|
|
|
None => "".to_string(),
|
|
|
|
|
},
|
|
|
|
|
next: match article.next {
|
|
|
|
|
Some(a) => a,
|
|
|
|
|
None => "".to_string(),
|
|
|
|
|
},
|
2024-03-24 10:45:16 -04:00
|
|
|
};
|
2024-05-17 14:55:30 -04:00
|
|
|
let template = ArticleTemplate {
|
|
|
|
|
active_navbar: NavBar::BLOG,
|
|
|
|
|
content: article.content,
|
|
|
|
|
footer: footer.to_string(),
|
|
|
|
|
};
|
2024-05-11 07:53:20 -04:00
|
|
|
HtmlTemplate(template)
|
2024-03-24 10:45:16 -04:00
|
|
|
}
|
2024-05-11 09:32:29 -04:00
|
|
|
|
|
|
|
|
pub async fn get_articles_as_links_list(pool: &PgPool) -> Result<Vec<String>, Box<dyn Error>> {
|
|
|
|
|
let mut articles: Vec<Article> = match Article::read_all(pool).await {
|
|
|
|
|
Ok(a) => a.iter().map(|x| *x.clone()).collect(),
|
|
|
|
|
Err(_) => panic!("Not an article at all!!!!"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
articles.sort_by(|a, b| b.date.cmp(&a.date));
|
|
|
|
|
|
|
|
|
|
let list: Vec<String> = articles
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|article| {
|
|
|
|
|
format!(
|
|
|
|
|
"<li><a href=\"/blog/{}\">{}</a></li>",
|
|
|
|
|
article.reference, article.title
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
Ok(list)
|
|
|
|
|
}
|