Adding recent articles back to blog. Cleaning up appstate

This commit is contained in:
Awstin 2024-10-01 21:24:28 -04:00
parent ae530431d7
commit a13ca49fa8
7 changed files with 32 additions and 194 deletions

View file

@ -1,86 +0,0 @@
use super::blog::get_articles_as_links_list;
use crate::{
database::{link::{Link, LinkType}, PsqlData},
html::AppState,
};
use axum::{response::IntoResponse, routing::get, Extension, Router};
use sqlx::PgPool;
use std::error::Error;
use rand::{seq::SliceRandom, thread_rng};
pub fn get_router() -> Router {
Router::new()
.route("/articles", get(blogs))
.route("/recentarticles", get(recent_blogs))
.route("/blogrolllinks", get(blogroll_links))
.route("/articlelinks", get(article_links))
}
async fn blogs(state: Extension<AppState>) -> impl IntoResponse {
let db_pool = &state.db;
let article_list: Vec<String> = get_articles_as_links_list(db_pool)
.await
.expect("couldn't get articles");
article_list.join("\n")
}
async fn recent_blogs(state: Extension<AppState>) -> impl IntoResponse {
let db_pool = &state.db;
let article_list: Vec<String> = get_articles_as_links_list(db_pool)
.await
.expect("couldn't get articles");
let (article_head, _) = article_list.split_at(5);
article_head.join("\n")
}
async fn blogroll_links(state: Extension<AppState>) -> impl IntoResponse {
let db_pool = &state.db;
let blogroll_list: Vec<String> = get_links_as_list(db_pool, LinkType::BLOG)
.await
.expect("couldn't get blogroll links");
blogroll_list.join("\n<hr>\n")
}
async fn article_links(state: Extension<AppState>) -> impl IntoResponse {
let db_pool = &state.db;
let blogroll_list: Vec<String> = get_links_as_list(db_pool, LinkType::ARTICLE)
.await
.expect("couldn't get blogroll links");
blogroll_list.join("\n<hr>\n")
}
pub async fn get_links_as_list(pool: &PgPool, link_type: LinkType) -> Result<Vec<String>, Box<dyn Error>> {
let mut links: Vec<Link> = match Link::read_all(pool).await {
Ok(a) => a.iter().map(|x| *x.clone()).collect(),
Err(_) => Vec::new(),
};
let mut rng = thread_rng();
links.shuffle(&mut rng);
let list: Vec<String> = links
.iter()
.filter(|link| link.link_type == link_type)
.map(|link| {
let title: String = match &link.title {
Some(t) => t.to_string(),
None => link.url.clone(),
};
format!(
"<li><a href=\"{}\">{}</a>:<br>{}</li>",
link.url,
title,
match &link.description {
Some(d) => d,
None => "",
}
)
})
.collect();
Ok(list)
}

View file

@ -8,10 +8,7 @@ use axum::{
use sqlx::PgPool;
use std::{collections::HashMap, error::Error};
use super::{
templates::{ArticleTemplate, BlogFooterTemplate, BlogTemplate, HtmlTemplate},
AppState,
};
use super::templates::{ArticleTemplate, BlogFooterTemplate, BlogTemplate, HtmlTemplate};
pub fn get_router() -> Router {
Router::new()
@ -19,23 +16,22 @@ pub fn get_router() -> Router {
.route("/:article", get(article))
}
async fn blog(state: Extension<AppState>) -> impl IntoResponse {
async fn blog(Extension(pool): Extension<PgPool>) -> impl IntoResponse {
let blog_page = BlogTemplate {
articles: match get_articles_date_sorted(&state.db).await {
articles: match get_articles_date_sorted(&pool).await {
Ok(list) => list,
Err(_) => Vec::new(),
}
},
};
HtmlTemplate(blog_page)
}
async fn article(
state: Extension<AppState>,
Extension(pool): Extension<PgPool>,
Path(params): Path<HashMap<String, String>>,
) -> Result<impl IntoResponse, StatusCode> {
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 {
let article: Article = match Article::read_by_reference(&pool, article_id).await {
Ok(a) => *a,
Err(_) => return Err(StatusCode::NOT_FOUND),
};

View file

@ -1,11 +1,5 @@
use sqlx::PgPool;
pub mod blog;
pub mod garden;
pub mod root;
pub mod templates;
#[derive(Clone)]
pub struct AppState {
pub db: PgPool,
}

View file

@ -1,80 +0,0 @@
use achubb_database::data::{project::Project, PsqlData};
use askama::Template;
use axum::extract::{Extension, Path};
use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::{routing::get, Router};
use sqlx::PgPool;
use std::{collections::HashMap, error::Error};
use super::{root::AppState, ArticleTemplate, HtmlTemplate};
pub fn get_router() -> Router {
Router::new()
.route("/", get(projects))
.route("/:project", get(project))
}
pub async fn projects(state: Extension<AppState>) -> impl IntoResponse {
let db_pool = &state.db;
let list: Vec<String> = get_projects_as_links_list(db_pool)
.await
.expect("couldn't get projects");
let template = ProjectsTemplate {
project_list: list.join("\n"),
};
HtmlTemplate(template)
}
#[derive(Template)]
#[template(path = "projects.html")]
struct ProjectsTemplate {
project_list: String,
}
async fn project(
state: Extension<AppState>,
Path(params): Path<HashMap<String, String>>,
) -> Result<impl IntoResponse, StatusCode> {
let db_pool = &state.db;
let project_id: &String = params.get("project").unwrap();
let project: Project = match Project::read_by_reference(db_pool, project_id).await {
Ok(a) => *a,
Err(_) => return Err(StatusCode::NOT_FOUND),
};
let footer: &str = "<a href=\"/projects\">Back to Projects</a>";
let template = ArticleTemplate {
content: project
.content
.expect("Should have had content if it got this far"),
footer: footer.to_string(),
};
Ok(HtmlTemplate(template))
}
pub async fn get_projects_as_links_list(pool: &PgPool) -> Result<Vec<String>, Box<dyn Error>> {
let mut projects: Vec<Project> = match Project::read_all(pool).await {
Ok(a) => a.iter().map(|x| *x.clone()).collect(),
Err(_) => Vec::new(),
};
projects.sort_by(|a, b| b.date.cmp(&a.date));
let list: Vec<String> = projects
.iter()
.map(|project| {
if project.blog {
format!(
"<li><a href=\"/blog/{}\">{}</a></li>",
project.reference, project.title
)
} else {
format!(
"<li><a href=\"/projects/{}\">{}</a></li>",
project.reference, project.title
)
}
})
.collect();
Ok(list)
}

View file

@ -14,16 +14,16 @@ use crate::database::{
};
use super::{
blog, garden,
blog::{self, get_articles_date_sorted},
garden,
templates::{
AboutTemplate, AiTemplate, BlogrollTemplate, ContactTemplate, GiftsTemplate, HomeTemplate, HtmlTemplate, InterestsTemplate, LinksPageTemplate, NowTemplate, UsesTemplate
AboutTemplate, AiTemplate, BlogrollTemplate, ContactTemplate, GiftsTemplate, HomeTemplate,
HtmlTemplate, InterestsTemplate, LinksPageTemplate, NowTemplate, UsesTemplate,
},
AppState,
};
pub fn get_router(pool: PgPool) -> Router {
let assets_path = std::env::current_dir().unwrap();
let state = AppState { db: pool };
Router::new()
.nest("/blog", blog::get_router())
.nest("/garden", garden::get_router())
@ -45,11 +45,15 @@ pub fn get_router(pool: PgPool) -> Router {
"/robots.txt",
get(|| async { Redirect::permanent("/assets/robots.txt") }),
)
.layer(Extension(state))
.layer(Extension(pool))
}
async fn home() -> impl IntoResponse {
HtmlTemplate(HomeTemplate {})
async fn home(Extension(pool): Extension<PgPool>) -> impl IntoResponse {
let mut articles = get_articles_date_sorted(&pool).await.unwrap();
articles.truncate(5);
HtmlTemplate(HomeTemplate {
recent_articles: articles,
})
}
async fn now() -> impl IntoResponse {
@ -80,9 +84,9 @@ async fn gifts() -> impl IntoResponse {
HtmlTemplate(GiftsTemplate {})
}
async fn blogroll(state: Extension<AppState>) -> impl IntoResponse {
async fn blogroll(Extension(pool): Extension<PgPool>) -> impl IntoResponse {
let blogroll_page = BlogrollTemplate {
blogs: match get_links_as_list(&state.db, LinkType::BLOG).await {
blogs: match get_links_as_list(&pool, LinkType::BLOG).await {
Ok(list) => list,
Err(_) => Vec::new(),
},
@ -90,9 +94,9 @@ async fn blogroll(state: Extension<AppState>) -> impl IntoResponse {
HtmlTemplate(blogroll_page)
}
async fn links(state: Extension<AppState>) -> impl IntoResponse {
async fn links(Extension(pool): Extension<PgPool>) -> impl IntoResponse {
let links_page = LinksPageTemplate {
articles: match get_links_as_list(&state.db, LinkType::ARTICLE).await {
articles: match get_links_as_list(&pool, LinkType::ARTICLE).await {
Ok(list) => list,
Err(_) => Vec::new(),
},

View file

@ -110,7 +110,9 @@ pub struct InterestsTemplate {}
#[derive(Template)]
#[template(path = "home.html")]
pub struct HomeTemplate {}
pub struct HomeTemplate {
pub recent_articles: Vec<Article>,
}
#[derive(Template)]
#[template(path = "about.html")]

View file

@ -44,6 +44,13 @@
Chronological <a href="blog">stuff</a> that I have written.
Not adding to this as much with the focus more on the garden but if something is timely then will still be added as a blog post.
</p>
<h3>Most Recent Posts</h3>
<ul class="no-bul">
{% for article in recent_articles %}
<li><a href="/blog/{{article.reference}}">{{article.title}}</a></li>
{% endfor %}
</ul>
</section><br>
<section id="interests">
@ -81,6 +88,7 @@
How <a href="/ai">AI</a> is (or more accurately is not) used in this site and my work in general,
and why.
</p>
</section><br>
<section id="contact">
<h2>Contact Me</h2>