From 4dca4adf3785de0547eb2943efdbd6f0a97972ec Mon Sep 17 00:00:00 2001 From: Daniel Boros Date: Thu, 29 Aug 2024 08:40:10 +0200 Subject: [PATCH] fix: remove env --- Cargo.toml | 2 +- src/{posts.rs => api.rs} | 46 +++++++++++++++++++++++++-- src/app.rs | 2 +- src/home.rs | 68 ++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 2 +- src/main.rs | 9 ++++-- src/post.rs | 13 +++++++- 7 files changed, 130 insertions(+), 12 deletions(-) rename src/{posts.rs => api.rs} (73%) diff --git a/Cargo.toml b/Cargo.toml index 047dbbb..40a80fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ tracing = { version = "0.1", optional = true } http = "1" surrealdb = { version = "1.5.4", features = ["protocol-http"] } chrono = "0.4.38" -serde = "1.0.204" +serde = { version = "1.0.204", features = ["derive"] } serde_json = "1.0.122" pulldown-cmark = "0.11.0" serde-wasm-bindgen = "0.6.5" diff --git a/src/posts.rs b/src/api.rs similarity index 73% rename from src/posts.rs rename to src/api.rs index a54ef7a..ff7e14d 100644 --- a/src/posts.rs +++ b/src/api.rs @@ -63,14 +63,26 @@ impl Default for Post { } #[server(endpoint = "/posts")] -pub async fn select_posts() -> Result, ServerFnError> { +pub async fn select_posts( + #[server(default)] tags: Vec, +) -> Result, ServerFnError> { use crate::ssr::AppState; use chrono::{DateTime, Utc}; use leptos::expect_context; let AppState { db, .. } = expect_context::(); + let mut query = format!("SELECT *, author.* from post ORDER BY created_at DESC;"); + if !tags.is_empty() { + let tags = tags + .iter() + .map(|tag| format!(r#""{}""#, tag)) + .collect::>(); + query = format!( + "SELECT *, author.* from post WHERE tags CONTAINSANY [{0}] ORDER BY created_at DESC;", + tags.join(", ") + ); + } - let query = format!("SELECT *, author.* from post ORDER BY created_at DESC;"); let query = db.query(&query).await; if let Err(e) = query { @@ -90,6 +102,36 @@ pub async fn select_posts() -> Result, ServerFnError> { Ok(posts) } +#[server(endpoint = "/tags")] +pub async fn select_tags() -> Result, ServerFnError> { + use crate::ssr::AppState; + use leptos::expect_context; + + let AppState { db, .. } = expect_context::(); + + let query = format!("SELECT tags from post;"); + let query = db.query(&query).await; + + if let Err(e) = query { + return Err(ServerFnError::from(e)); + } + + #[derive(Debug, Clone, Serialize, Deserialize)] + struct Tags { + tags: Vec, + } + let tags = query?.take::>(0)?; + let mut tags = tags.iter().flat_map(|t| t.tags.clone()).collect::>(); + tags.sort(); + let tags = tags + .into_iter() + .collect::>() + .into_iter() + .collect(); + + Ok(tags) +} + #[server(endpoint = "/post")] pub async fn select_post(slug: String) -> Result { use crate::ssr::AppState; diff --git a/src/app.rs b/src/app.rs index f3c2bf5..c160ea7 100644 --- a/src/app.rs +++ b/src/app.rs @@ -28,7 +28,7 @@ pub fn App() -> impl IntoView { view! { }.into_view() }> - + diff --git a/src/home.rs b/src/home.rs index 355e1d1..455462e 100644 --- a/src/home.rs +++ b/src/home.rs @@ -1,14 +1,19 @@ use leptos::*; use leptos_router::*; -use crate::posts::{increment_views, select_posts}; +use crate::api::{increment_views, select_posts, select_tags}; #[component] pub fn Component() -> impl IntoView { let navigate = use_navigate(); - let posts = create_blocking_resource( + let selected_tags = create_rw_signal(Vec::::new()); + let tags = create_blocking_resource( || (), - move |_| async move { select_posts().await.unwrap_or_default() }, + move |_| async move { select_tags().await.unwrap_or_default() }, + ); + let posts = create_blocking_resource( + move || selected_tags.get(), + move |selected_tags| async move { select_posts(selected_tags).await.unwrap_or_default() }, ); let increment_view = create_action(move |id: &String| { let id = id.clone(); @@ -22,6 +27,63 @@ pub fn Component() -> impl IntoView { { let navigate = navigate.clone(); view! { +
+ + >(); + } else { + *prev = prev + .clone() + .into_iter() + .chain(std::iter::once(tag.clone())) + .collect(); + } + }); + } + } + class="px-2 py-1 rounded-lg transition-all duration-500 cursor-pointer hover:bg-white hover:text-black" + class=( + "bg-white", + { + let tag = tag.clone(); + move || selected_tags.get().contains(&tag) + }, + ) + class=( + "text-black", + { + let tag = tag.clone(); + move || selected_tags.get().contains(&tag) + }, + ) + > + {tag} + + } + } + /> +
(host).await.unwrap() } else { Surreal::new::(host).await.unwrap() }; - + db.signin(Root { username: &username, password: &password, diff --git a/src/post.rs b/src/post.rs index 3d95972..baaf011 100644 --- a/src/post.rs +++ b/src/post.rs @@ -1,8 +1,9 @@ use leptos::*; +use leptos_meta::*; use leptos_router::*; use pulldown_cmark::{html, Parser}; -use crate::posts::select_post; +use crate::api::select_post; #[component] pub fn Component() -> impl IntoView { @@ -15,6 +16,15 @@ pub fn Component() -> impl IntoView { view! { + {post + .get() + .unwrap_or_default() + .tags + .into_iter() + .map(|tag| { + view! { } + }) + .collect::>()} {move || { post.with(|post| { let post = post.clone().unwrap_or_default(); @@ -51,6 +61,7 @@ pub fn Component() -> impl IntoView { class="my-6 prose max-w-3xl mx-auto prose-h3:text-white prose-code:before:content-none prose-code:after:content-none prose-code:text-[#ffbd2e] prose-strong:text-white prose-h1:text-white prose-h1:text-3xl prose-h2:text-white prose-h2:text-2xl prose-ul:text-white prose-p:text-white prose-a:text-[#ffbd2e]" inner_html=html_output /> + } })