aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@blos.sm>2023-06-22 15:35:18 +0100
committerLibravatar cel 🌸 <cel@blos.sm>2023-06-22 15:35:18 +0100
commita135acf943ba0fc442dca69f43339921728b1ed4 (patch)
tree77d8ad93d8064db1f0b71601e8b13b165c787cb9
parent139c26158bba4ec09e7ba690ba6c9c11da620707 (diff)
downloadblossom-a135acf943ba0fc442dca69f43339921728b1ed4.tar.gz
blossom-a135acf943ba0fc442dca69f43339921728b1ed4.tar.bz2
blossom-a135acf943ba0fc442dca69f43339921728b1ed4.zip
implement blog tag filtering
-rw-r--r--src/main.rs46
-rw-r--r--src/posts/mod.rs55
-rw-r--r--src/posts/note.rs8
-rw-r--r--static/style.css4
-rw-r--r--templates/base.html.tera2
-rw-r--r--templates/blogpost-panel.html.tera2
-rw-r--r--templates/filtertags.html.tera4
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>