Add all tags in posts
This commit is contained in:
parent
91f2e4c116
commit
0436136cdd
2 changed files with 52 additions and 9 deletions
|
@ -9,6 +9,7 @@ cfg_if::cfg_if! {
|
||||||
pub posts: Vec<Arc<Post>>,
|
pub posts: Vec<Arc<Post>>,
|
||||||
pub posts_by_slug: HashMap<String, Arc<Post>>,
|
pub posts_by_slug: HashMap<String, Arc<Post>>,
|
||||||
pub posts_by_tag: HashMap<String, Vec<Arc<Post>>>,
|
pub posts_by_tag: HashMap<String, Vec<Arc<Post>>>,
|
||||||
|
pub tags: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
|
@ -21,6 +22,8 @@ cfg_if::cfg_if! {
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
||||||
|
let mut tags : Vec<String> = Vec::new();
|
||||||
let mut posts_by_slug : HashMap<String, Arc<Post>> = HashMap::new();
|
let mut posts_by_slug : HashMap<String, Arc<Post>> = HashMap::new();
|
||||||
let mut posts_by_tag : HashMap<String, Vec<Arc<Post>>> = HashMap::new();
|
let mut posts_by_tag : HashMap<String, Vec<Arc<Post>>> = HashMap::new();
|
||||||
|
|
||||||
|
@ -28,19 +31,26 @@ cfg_if::cfg_if! {
|
||||||
posts_by_slug.insert(post.metadata.slug.clone(), post.clone());
|
posts_by_slug.insert(post.metadata.slug.clone(), post.clone());
|
||||||
|
|
||||||
for tag in &post.metadata.tags {
|
for tag in &post.metadata.tags {
|
||||||
let tag = tag.to_lowercase();
|
let tag_lower = tag.to_lowercase();
|
||||||
let posts = posts_by_tag.entry(tag).or_default();
|
|
||||||
|
if let None = tags.iter().find(|t| t.to_lowercase().eq(&tag_lower)) {
|
||||||
|
tags.push(tag.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
let posts = posts_by_tag.entry(tag_lower).or_default();
|
||||||
posts.push(post.clone());
|
posts.push(post.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Loaded {} posts", posts.len());
|
log::info!("Loaded {} posts", posts.len());
|
||||||
log::info!("Found {} tags", posts_by_tag.len());
|
log::info!("Found {} tags in global", tags.len());
|
||||||
|
log::info!("Found {} tags from posts", posts_by_tag.len());
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
posts,
|
posts,
|
||||||
posts_by_slug,
|
posts_by_slug,
|
||||||
posts_by_tag,
|
posts_by_tag,
|
||||||
|
tags
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,16 @@ pub async fn get_posts(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn get_tags() -> Result<Vec<String>, ServerFnError> {
|
||||||
|
let data : actix_web::web::Data<crate::app::models::Data> = leptos_actix::extract().await?;
|
||||||
|
let data = data.into_inner();
|
||||||
|
let mut tags = data.tags.clone();
|
||||||
|
tags.sort();
|
||||||
|
|
||||||
|
Ok(tags)
|
||||||
|
}
|
||||||
|
|
||||||
#[server]
|
#[server]
|
||||||
pub async fn get_post(
|
pub async fn get_post(
|
||||||
slug: String
|
slug: String
|
||||||
|
@ -117,6 +127,7 @@ pub fn PostList() -> impl IntoView {
|
||||||
let query = use_query_map();
|
let query = use_query_map();
|
||||||
let tag = move || query.with(|query| query.get("tag").cloned());
|
let tag = move || query.with(|query| query.get("tag").cloned());
|
||||||
let posts = create_resource(move || tag(), move |_| get_posts(tag()));
|
let posts = create_resource(move || tag(), move |_| get_posts(tag()));
|
||||||
|
let tags = create_resource(|| (), move |_| get_tags());
|
||||||
|
|
||||||
let posts_view = move || {
|
let posts_view = move || {
|
||||||
posts.and_then(|posts| {
|
posts.and_then(|posts| {
|
||||||
|
@ -126,18 +137,40 @@ pub fn PostList() -> impl IntoView {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let tags_view = move || {
|
||||||
|
tags.and_then(|tags| {
|
||||||
|
tags.iter()
|
||||||
|
.map(|tag| {
|
||||||
|
let tag = tag.clone();
|
||||||
|
view! { <A class="tag" href=format!("/posts?tag={}", tag.clone())>{tag}</A> }
|
||||||
|
})
|
||||||
|
.collect_view()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
let filter_view = move || {
|
let filter_view = move || {
|
||||||
tag().map(|tag| Some(view! {
|
match tag() {
|
||||||
<div class="mx-auto max-w-3xl mb-5">
|
Some(tag) => {
|
||||||
Tag sélectionné : <A class="tag" href="/posts".to_string()>{tag}<leptos_icons::Icon icon=icondata::IoClose class="scale-125 ml-1 inline" /></A>
|
view! {
|
||||||
</div>
|
<A class="tag" href="/posts".to_string()>{tag}<leptos_icons::Icon icon=icondata::IoClose class="scale-125 ml-1 inline" /></A>
|
||||||
}))
|
}.into_view()
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
view! {
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{tags_view}
|
||||||
|
</div>
|
||||||
|
}.into_view()
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Suspense fallback=move || view! { <Loading title="Chargement des posts...".to_string() /> }>
|
<Suspense fallback=move || view! { <Loading title="Chargement des posts...".to_string() /> }>
|
||||||
<Nav/>
|
<Nav/>
|
||||||
{filter_view}
|
<div class="mx-auto max-w-3xl mb-5">
|
||||||
|
{filter_view}
|
||||||
|
</div>
|
||||||
<main class="posts">
|
<main class="posts">
|
||||||
<div class="posts__cards">{posts_view}</div>
|
<div class="posts__cards">{posts_view}</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
Loading…
Reference in a new issue