Adding recent articles back to blog. Cleaning up appstate
This commit is contained in:
parent
ae530431d7
commit
a13ca49fa8
7 changed files with 32 additions and 194 deletions
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -8,10 +8,7 @@ use axum::{
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use std::{collections::HashMap, error::Error};
|
use std::{collections::HashMap, error::Error};
|
||||||
|
|
||||||
use super::{
|
use super::templates::{ArticleTemplate, BlogFooterTemplate, BlogTemplate, HtmlTemplate};
|
||||||
templates::{ArticleTemplate, BlogFooterTemplate, BlogTemplate, HtmlTemplate},
|
|
||||||
AppState,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn get_router() -> Router {
|
pub fn get_router() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
|
|
@ -19,23 +16,22 @@ pub fn get_router() -> Router {
|
||||||
.route("/:article", get(article))
|
.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 {
|
let blog_page = BlogTemplate {
|
||||||
articles: match get_articles_date_sorted(&state.db).await {
|
articles: match get_articles_date_sorted(&pool).await {
|
||||||
Ok(list) => list,
|
Ok(list) => list,
|
||||||
Err(_) => Vec::new(),
|
Err(_) => Vec::new(),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
HtmlTemplate(blog_page)
|
HtmlTemplate(blog_page)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn article(
|
async fn article(
|
||||||
state: Extension<AppState>,
|
Extension(pool): Extension<PgPool>,
|
||||||
Path(params): Path<HashMap<String, String>>,
|
Path(params): Path<HashMap<String, String>>,
|
||||||
) -> Result<impl IntoResponse, StatusCode> {
|
) -> Result<impl IntoResponse, StatusCode> {
|
||||||
let db_pool = &state.db;
|
|
||||||
let article_id: &String = params.get("article").unwrap();
|
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,
|
Ok(a) => *a,
|
||||||
Err(_) => return Err(StatusCode::NOT_FOUND),
|
Err(_) => return Err(StatusCode::NOT_FOUND),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
use sqlx::PgPool;
|
|
||||||
|
|
||||||
pub mod blog;
|
pub mod blog;
|
||||||
pub mod garden;
|
pub mod garden;
|
||||||
pub mod root;
|
pub mod root;
|
||||||
pub mod templates;
|
pub mod templates;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct AppState {
|
|
||||||
pub db: PgPool,
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -14,16 +14,16 @@ use crate::database::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
blog, garden,
|
blog::{self, get_articles_date_sorted},
|
||||||
|
garden,
|
||||||
templates::{
|
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 {
|
pub fn get_router(pool: PgPool) -> Router {
|
||||||
let assets_path = std::env::current_dir().unwrap();
|
let assets_path = std::env::current_dir().unwrap();
|
||||||
let state = AppState { db: pool };
|
|
||||||
Router::new()
|
Router::new()
|
||||||
.nest("/blog", blog::get_router())
|
.nest("/blog", blog::get_router())
|
||||||
.nest("/garden", garden::get_router())
|
.nest("/garden", garden::get_router())
|
||||||
|
|
@ -45,11 +45,15 @@ pub fn get_router(pool: PgPool) -> Router {
|
||||||
"/robots.txt",
|
"/robots.txt",
|
||||||
get(|| async { Redirect::permanent("/assets/robots.txt") }),
|
get(|| async { Redirect::permanent("/assets/robots.txt") }),
|
||||||
)
|
)
|
||||||
.layer(Extension(state))
|
.layer(Extension(pool))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn home() -> impl IntoResponse {
|
async fn home(Extension(pool): Extension<PgPool>) -> impl IntoResponse {
|
||||||
HtmlTemplate(HomeTemplate {})
|
let mut articles = get_articles_date_sorted(&pool).await.unwrap();
|
||||||
|
articles.truncate(5);
|
||||||
|
HtmlTemplate(HomeTemplate {
|
||||||
|
recent_articles: articles,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn now() -> impl IntoResponse {
|
async fn now() -> impl IntoResponse {
|
||||||
|
|
@ -80,9 +84,9 @@ async fn gifts() -> impl IntoResponse {
|
||||||
HtmlTemplate(GiftsTemplate {})
|
HtmlTemplate(GiftsTemplate {})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn blogroll(state: Extension<AppState>) -> impl IntoResponse {
|
async fn blogroll(Extension(pool): Extension<PgPool>) -> impl IntoResponse {
|
||||||
let blogroll_page = BlogrollTemplate {
|
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,
|
Ok(list) => list,
|
||||||
Err(_) => Vec::new(),
|
Err(_) => Vec::new(),
|
||||||
},
|
},
|
||||||
|
|
@ -90,9 +94,9 @@ async fn blogroll(state: Extension<AppState>) -> impl IntoResponse {
|
||||||
HtmlTemplate(blogroll_page)
|
HtmlTemplate(blogroll_page)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn links(state: Extension<AppState>) -> impl IntoResponse {
|
async fn links(Extension(pool): Extension<PgPool>) -> impl IntoResponse {
|
||||||
let links_page = LinksPageTemplate {
|
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,
|
Ok(list) => list,
|
||||||
Err(_) => Vec::new(),
|
Err(_) => Vec::new(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,9 @@ pub struct InterestsTemplate {}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "home.html")]
|
#[template(path = "home.html")]
|
||||||
pub struct HomeTemplate {}
|
pub struct HomeTemplate {
|
||||||
|
pub recent_articles: Vec<Article>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "about.html")]
|
#[template(path = "about.html")]
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,13 @@
|
||||||
Chronological <a href="blog">stuff</a> that I have written.
|
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.
|
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>
|
</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><br>
|
||||||
|
|
||||||
<section id="interests">
|
<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,
|
How <a href="/ai">AI</a> is (or more accurately is not) used in this site and my work in general,
|
||||||
and why.
|
and why.
|
||||||
</p>
|
</p>
|
||||||
|
</section><br>
|
||||||
|
|
||||||
<section id="contact">
|
<section id="contact">
|
||||||
<h2>Contact Me</h2>
|
<h2>Contact Me</h2>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue