diff options
author | cel 🌸 <cel@blos.sm> | 2023-06-22 15:35:18 +0100 |
---|---|---|
committer | cel 🌸 <cel@blos.sm> | 2023-06-22 15:35:18 +0100 |
commit | a135acf943ba0fc442dca69f43339921728b1ed4 (patch) | |
tree | 77d8ad93d8064db1f0b71601e8b13b165c787cb9 | |
parent | 139c26158bba4ec09e7ba690ba6c9c11da620707 (diff) | |
download | blossom-a135acf943ba0fc442dca69f43339921728b1ed4.tar.gz blossom-a135acf943ba0fc442dca69f43339921728b1ed4.tar.bz2 blossom-a135acf943ba0fc442dca69f43339921728b1ed4.zip |
implement blog tag filtering
-rw-r--r-- | src/main.rs | 46 | ||||
-rw-r--r-- | src/posts/mod.rs | 55 | ||||
-rw-r--r-- | src/posts/note.rs | 8 | ||||
-rw-r--r-- | static/style.css | 4 | ||||
-rw-r--r-- | templates/base.html.tera | 2 | ||||
-rw-r--r-- | templates/blogpost-panel.html.tera | 2 | ||||
-rw-r--r-- | templates/filtertags.html.tera | 4 |
7 files changed, 80 insertions, 41 deletions
diff --git a/src/main.rs b/src/main.rs index c08c2e1..40f546d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod scrobbles; mod skweets; use std::borrow::Cow; +use std::collections::HashSet; use rocket::fs::{relative, FileServer}; use rocket::http::Status; @@ -47,24 +48,6 @@ async fn home(clients: &State<Clients>) -> Template { ) } -#[get("/blog")] -async fn blog() -> Template { - let mut blogposts = posts::get_blogposts().await.unwrap_or_default(); - let tags = posts::get_tags(&blogposts); - for blogpost in &mut blogposts { - blogpost.render().await; - } - let reverse = "reverse".to_owned(); - Template::render( - "blog", - context! { - reverse, - blogposts, - tags, - }, - ) -} - #[get("/blog/<blogpost>")] async fn blogpost(blogpost: &str) -> Result<Template> { let mut blogpost = posts::get_blogpost(blogpost).await?; @@ -77,6 +60,33 @@ async fn blogpost(blogpost: &str) -> Result<Template> { )) } +#[get("/blog?<filter>")] +async fn blog(filter: Vec<String>) -> Result<Template> { + let mut blogposts = posts::get_blogposts().await?; + let tags: Vec<String> = posts::get_tags(&blogposts) + .into_iter() + .map(|tag| tag.to_owned()) + .collect(); + let mut filter_hashset: HashSet<String> = HashSet::new(); + if !filter.is_empty() { + filter_hashset.extend(filter.into_iter()); + blogposts = posts::filter_by_tags(blogposts, &filter_hashset); + } + for blogpost in &mut blogposts { + blogpost.render().await?; + } + let reverse = true; + Ok(Template::render( + "blog", + context! { + reverse, + tags, + filter_hashset, + blogposts, + }, + )) +} + #[get("/contact")] async fn contact() -> Template { Template::render("contact", context! {}) diff --git a/src/posts/mod.rs b/src/posts/mod.rs index be1e1a9..2dc5c4b 100644 --- a/src/posts/mod.rs +++ b/src/posts/mod.rs @@ -1,3 +1,6 @@ +mod article; +mod note; + use std::collections::HashSet; use async_trait::async_trait; @@ -16,12 +19,6 @@ enum PostType { Note, } -enum TextFormat { - Markdown, - Plaintext, - Html, -} - #[derive(Debug)] pub struct Post<D: Content> { // id: i64, @@ -34,7 +31,7 @@ pub struct Post<D: Content> { data: D, } -impl<D: Content + Serialize> Post<D> { +impl<D: Content> Post<D> { pub async fn render(&mut self) -> Result<()> { self.render = Some(self.data.render().await?); Ok(()) @@ -74,6 +71,8 @@ pub async fn get_blogposts() -> Result<Vec<Post<Article>>> { let blogpost = Post::try_from(blogpost).await.unwrap(); blogposts.push(blogpost); } + blogposts.sort_by_key(|post| post.created_at); + blogposts.reverse(); Ok(blogposts) } @@ -87,21 +86,45 @@ pub async fn get_blogpost(post_name: &str) -> Result<Post<Article>> { path: file.path().to_str().unwrap_or_default().to_owned(), name: name.to_owned(), }; - let blogpost = Post::try_from(blogpost).await.unwrap(); + let blogpost = Post::try_from(blogpost).await?; return Ok(blogpost); } } Err(BlossomError::NotFound(Status::new(404))) } -pub fn get_tags<D: Content>(posts: &Vec<Post<D>>) -> HashSet<String> { - posts.into_iter().fold(HashSet::new(), |mut acc, post| { - let tags = &post.tags; - for tag in tags { - acc.insert(tag.to_owned()); - } - acc - }) +pub fn get_tags<D: Content>(posts: &Vec<Post<D>>) -> Vec<&String> { + let mut tags = posts + .into_iter() + .fold(HashSet::new(), |mut acc, post| { + let tags = &post.tags; + for tag in tags { + acc.insert(tag); + } + acc + }) + .into_iter() + .collect::<Vec<_>>(); + tags.sort(); + tags +} + +pub fn filter_by_tags<'p, D: Content>( + posts: Vec<Post<D>>, + filter_tags: &HashSet<String>, +) -> Vec<Post<D>> { + posts + .into_iter() + .filter(|post| { + for tag in &post.tags { + match filter_tags.contains(tag) { + true => return true, + false => continue, + } + } + false + }) + .collect() } #[async_trait] diff --git a/src/posts/note.rs b/src/posts/note.rs index 95655d4..d7fa6c9 100644 --- a/src/posts/note.rs +++ b/src/posts/note.rs @@ -1 +1,7 @@ -struct note +enum TextFormat { + Markdown, + Plaintext, + Html, +} + +struct Note {} diff --git a/static/style.css b/static/style.css index 889c6ff..bf3f649 100644 --- a/static/style.css +++ b/static/style.css @@ -329,9 +329,9 @@ iframe { } .tags { - display: flexbox; + display: flex; flex-wrap: wrap; - gap: 0.5em; + gap: 1em; } .tags a { diff --git a/templates/base.html.tera b/templates/base.html.tera index 3874df3..ece268c 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -56,7 +56,7 @@ </ul> </nav> - <main class="{% if reverse %}{{ reverse }}{% endif %}"> + <main class="{% if reverse %}reverse{% endif %}"> <div class="main-content"> {% block content %} diff --git a/templates/blogpost-panel.html.tera b/templates/blogpost-panel.html.tera index 061d87b..64f064c 100644 --- a/templates/blogpost-panel.html.tera +++ b/templates/blogpost-panel.html.tera @@ -1,7 +1,7 @@ <div class="panel content blogpost"> <h1 class="title">{{ blogpost.subject }}</h1> <h2 class="created-at">{{ blogpost.created_at }} <a href="/blog/{{ blogpost.data.name }}">permalink</a></h2> - <div class="tags">{% for tag in blogpost.tags %}<a class="tag" href="/tag/{{ tag }}">{{ tag }}</a>{% endfor %}</div> + <div class="tags">{% for tag in blogpost.tags %}<a class="tag {% if filter_hashset %}{% if tag in filter_hashset %}active{% endif %}{% endif %}" href="/blog?filter={{ tag }}">{{ tag }}</a>{% endfor %}</div> <div class="blogpost-content"> {{ blogpost.render }} </div> diff --git a/templates/filtertags.html.tera b/templates/filtertags.html.tera index da001e8..f79ee94 100644 --- a/templates/filtertags.html.tera +++ b/templates/filtertags.html.tera @@ -1,7 +1,7 @@ <div class="panel" id="filter-tags"> -<h2>filter tag</h2> +<h2>filter by tags</h2> <div class="tags"> - {% for tag in tags %}<a href="/blog/tag/{{ tag }}">{{ tag }}</a>{% endfor %} + {% for tag in tags %}<a class="{% if tag in filter_hashset %}active{% endif %}" href="{% if tag in filter_hashset %}/blog{% else %}/blog?filter={{ tag }}{% endif %}">{{ tag }}</a>{% endfor %} </div> <br> </div> |