diff --git a/src/artifact/artifact_impl.rs b/src/artifact/artifact_impl.rs index 71deb0b..cab0bfa 100644 --- a/src/artifact/artifact_impl.rs +++ b/src/artifact/artifact_impl.rs @@ -2,7 +2,8 @@ use yew::prelude::*; use crate::{ artifact::artifact_model::EntryStatus, - html_utils::{make_tag, scroll::try_scroll_to}, + html_utils::{render_text_tag, scroll::try_scroll_to}, + pages::HallMsg, }; use super::artifact_model::Article; @@ -17,9 +18,10 @@ pub enum ArticleMsg { Toggle(bool), } -#[derive(Properties, Deserialize, Debug)] +#[derive(Properties, Debug)] pub struct ArticleProps { pub article: Article, + pub hall_cb: Callback, } impl PartialEq for ArticleProps { @@ -78,27 +80,43 @@ impl Component for ArticleComponent { .props() .article .tags - .iter() + .clone() + .into_iter() .map(|tag| { - Html::from_html_unchecked( - make_tag( - tag, - match tag.as_str() { - "ADT" => "green", - "Recursion" => "yellow", - "Sorting" => "blue", - "Graph" => "purple", - "Math" => "sky", - "Concurrency" => "cyan", - "OS" | "Dangerous" | "Bare Metal" => "red", - _ => "gray", - }, - ) - .into(), - ) + let tag_clone = tag.clone(); + let emitter = ctx.props().hall_cb.clone(); + html! { + + {Html::from_html_unchecked( + render_text_tag(&tag).into() + )} + + } }) .collect(); + let emitter = ctx.props().hall_cb.clone(); + let language_clone = ctx.props().article.language.clone(); + let language_tag = html! { + + {Html::from_html_unchecked( + ctx.props().article.language.to_tag().into() + )} + + }; + + // actual article let rendered = match self.show { true => { let content = match ctx.props().article.status { @@ -196,7 +214,8 @@ impl Component for ArticleComponent {

- {Html::from_html_unchecked(ctx.props().article.language.to_tag().into())}{tags} + {language_tag} + {tags}

diff --git a/src/artifact/lang_utils.rs b/src/artifact/lang_utils.rs index 07577a2..b188dab 100644 --- a/src/artifact/lang_utils.rs +++ b/src/artifact/lang_utils.rs @@ -1,5 +1,5 @@ use super::Language; -use crate::html_utils::make_tag; +use crate::html_utils::render_text_tag; impl PartialOrd for Language { fn partial_cmp(&self, other: &Self) -> Option { @@ -14,6 +14,19 @@ impl Ord for Language { } impl Language { + pub fn to_string(&self) -> String { + match self { + Language::Haskell => "Haskell".to_string(), + Language::Rust => "Rust".to_string(), + Language::Python => "Python".to_string(), + Language::Go => "Go".to_string(), + Language::C => "C".to_string(), + Language::OCaml => "OCaml".to_string(), + Language::Bash => "Bash".to_string(), + Language::Clojure => "Clojure".to_string(), + } + } + pub fn icon(&self) -> &'static str { // https://devicon.dev/ match self { @@ -39,16 +52,7 @@ impl Language { } pub fn to_tag(&self) -> String { - match self { - Language::Haskell => make_tag("Haskell", "purple"), - Language::Rust => make_tag("Rust", "orange"), - Language::Python => make_tag("Python", "yellow"), - Language::Go => make_tag("Go", "cyan"), - Language::C => make_tag("C", "gray"), - Language::OCaml => make_tag("OCaml", "blue"), - Language::Bash => make_tag("Bash", "green"), - Language::Clojure => make_tag("Clojure", "purple"), - } + render_text_tag(&self.to_string()) } } diff --git a/src/html_utils/mod.rs b/src/html_utils/mod.rs index 4edde9a..9120f39 100644 --- a/src/html_utils/mod.rs +++ b/src/html_utils/mod.rs @@ -1,3 +1,3 @@ mod tags; -pub use tags::make_tag; +pub use tags::{make_tag, render_text_tag}; pub mod scroll; diff --git a/src/html_utils/tags.rs b/src/html_utils/tags.rs index a2f5ffe..99f1c64 100644 --- a/src/html_utils/tags.rs +++ b/src/html_utils/tags.rs @@ -2,3 +2,28 @@ pub fn make_tag(text: &str, color: &str) -> String { let color_class = format!("inline-flex items-center rounded-md mr-2 px-2 py-1 text-xs font-medium ring-1 ring-inset bg-{}-500/20 text-{}-400 ring-{}-500/80", color, color, color); format!(r#"{}"#, color_class, text) } + +pub fn render_text_tag(tag: &str) -> String { + make_tag( + tag, + match tag { + "Rust" => "orange", + "C" => "red", + "Python" => "yellow", + "Haskell" => "purple", + "OCaml" => "blue", + "Bash" => "green", + "Clojure" => "purple", + "Go" => "cyan", + + "ADT" => "green", + "Recursion" => "yellow", + "Sorting" => "blue", + "Graph" => "purple", + "Math" => "sky", + "Concurrency" => "cyan", + "OS" | "Dangerous" | "Bare Metal" => "red", + _ => "gray", + }, + ) +} diff --git a/src/pages/hall.rs b/src/pages/hall.rs index 88fe1ee..1949442 100644 --- a/src/pages/hall.rs +++ b/src/pages/hall.rs @@ -1,12 +1,14 @@ use yew::prelude::*; use crate::artifact::{ArticleComponent, BuiltYaml, ExhibitionHall}; +use crate::html_utils::render_text_tag; use crate::html_utils::scroll::try_scroll_to; use crate::pages::hall_components::HallNav; pub struct HallComponent { active_hall: Option, menu_active: bool, + filter_tags: Vec, } #[derive(Properties, PartialEq)] @@ -14,6 +16,8 @@ pub struct HallProps {} pub enum HallMsg { GoToHall(Option), + ToggleTag(String), + ClearTags, } static HALLROOT: &str = "hall_entrance"; @@ -26,6 +30,7 @@ impl Component for HallComponent { Self { active_hall: None, menu_active: false, + filter_tags: vec![], } } @@ -41,6 +46,20 @@ impl Component for HallComponent { try_scroll_to(HALLROOT); true } + HallMsg::ToggleTag(tag) => { + if self.filter_tags.contains(&tag) { + self.filter_tags.retain(|t| t != &tag); + } else { + self.filter_tags.push(tag); + } + try_scroll_to(HALLROOT); + true + } + HallMsg::ClearTags => { + self.filter_tags = vec![]; + try_scroll_to(HALLROOT); + true + } } } @@ -55,7 +74,7 @@ impl Component for HallComponent { }; let desc = match &self.active_hall { Some(hall) => hall.desc(), - None => "You're currently viewing all available artifacts. Select a hall (🏛️) at bottom left to view its artifacts.", + None => "You're currently viewing all artifacts. Select a hall (🏛️), or click on the tags to filter the artifacts." }; let mut loaded_articles = built_yaml.artifacts; @@ -68,9 +87,21 @@ impl Component for HallComponent { (_, None) => true, (None, _) => false, }) + .filter(|article| match &self.filter_tags.len() { + 0 => true, + _ => { + let mut article_tags = article.tags.clone(); + article_tags.push(article.language.to_string()); + self.filter_tags + .iter() + .all(|tag| article_tags.contains(tag)) + } + }) .map(|article| { + let emitter = ctx.link().clone(); + let hall_cb = Callback::from(move |msg| emitter.send_message(msg)); html! { - + } }) .collect::>(); @@ -78,12 +109,52 @@ impl Component for HallComponent { let emitter = ctx.link().clone(); let nav_cb = Callback::from(move |msg| emitter.send_message(msg)); + let clear_filter_button = match self.filter_tags.len() { + 0 => html! {}, + _ => { + let clear_individual_tags = self + .filter_tags + .iter() + .map(|tag| { + let tagc= tag.clone(); + html! { +
+ { + Html::from_html_unchecked( + render_text_tag(&tag).into() + ) + } +
+ } + }) + .collect::(); + html! { +
+
+
+ +
+
+ {clear_individual_tags} +
+
+
+ } + } + }; + html! { <> + {clear_filter_button} - // menu block for mobile devices -
+
diff --git a/src/pages/mod.rs b/src/pages/mod.rs index 810c68b..a20dd33 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -9,7 +9,7 @@ pub use wip::Wip; mod hall; mod hall_components; -pub use hall::HallComponent; +pub use hall::{HallComponent, HallMsg}; mod nav; pub use nav::Nav; diff --git a/src/pages/nav.rs b/src/pages/nav.rs index ee1a710..46432c3 100644 --- a/src/pages/nav.rs +++ b/src/pages/nav.rs @@ -1,4 +1,3 @@ -use log::info; use yew::prelude::*; use yew_router::scope_ext::RouterScopeExt; @@ -33,7 +32,6 @@ impl Component for Nav { fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { Msg::ToggleSidebar(show) => { - info!("Sidebar toggled: {}", show); self.show_sidebar = show; true }