diff --git a/axum_server/src/main.rs b/axum_server/src/main.rs index f3268e7..2699dd0 100644 --- a/axum_server/src/main.rs +++ b/axum_server/src/main.rs @@ -10,6 +10,7 @@ mod pages; mod post_list; mod post_parser; mod router; +mod tag_list; // mod template; #[tokio::main] diff --git a/axum_server/src/pages/index.rs b/axum_server/src/pages/index.rs index dec6797..a8a1b49 100644 --- a/axum_server/src/pages/index.rs +++ b/axum_server/src/pages/index.rs @@ -1,8 +1,12 @@ use askama::Template; +use axum::http::StatusCode; -use crate::components::{ - site_footer::{render_site_footer, SiteFooter}, - site_header::HeaderProps, +use crate::{ + components::{ + site_footer::{render_site_footer, SiteFooter}, + site_header::HeaderProps, + }, + tag_list::get_popular_blog_tags, }; #[derive(Template)] @@ -10,12 +14,24 @@ use crate::components::{ pub struct IndexTemplate { site_footer: SiteFooter, header_props: HeaderProps, + blog_tags: Vec, } -pub async fn render_index() -> IndexTemplate { - let site_footer = render_site_footer().await; - IndexTemplate { +pub async fn render_index() -> Result { + let site_footer = tokio::spawn(render_site_footer()); + let blog_tags = tokio::spawn(get_popular_blog_tags()); + + let blog_tags = blog_tags + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)??; + + let site_footer = site_footer + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + Ok(IndexTemplate { site_footer, header_props: HeaderProps::default(), - } + blog_tags, + }) } diff --git a/axum_server/src/pages/post_list.rs b/axum_server/src/pages/post_list.rs index d180fa3..f2599cc 100644 --- a/axum_server/src/pages/post_list.rs +++ b/axum_server/src/pages/post_list.rs @@ -51,7 +51,6 @@ pub async fn render_post_list(tag: Option>) -> Result HeaderProps::with_back_link(Link { href: "/blog".to_string(), @@ -68,6 +67,3 @@ pub async fn render_post_list(tag: Option>) -> Result Result, StatusCode> { + const TAGS_LENGTH: usize = 7; + + let post_list = get_post_list::().await?; + let tags_sum = post_list + .into_iter() + .flat_map(|post| post.metadata.tags) + .fold(HashMap::new(), |mut acc, tag| { + *acc.entry(tag).or_insert(0) += 1; + acc + }); + + let mut sorted_tags_by_count: Vec<_> = tags_sum.into_iter().collect(); + sorted_tags_by_count.sort_by_key(|&(_, count)| std::cmp::Reverse(count)); + + // Log the counts + for (tag, count) in &sorted_tags_by_count { + debug!("Tag: {}, Count: {}", tag, count); + } + + let popular_blog_tags = sorted_tags_by_count + .into_iter() + .map(|tag_count| tag_count.0) + .filter(|tag| tag != "dev") + .take(TAGS_LENGTH) + .collect::>(); + + Ok(popular_blog_tags) +} diff --git a/axum_server/styles/input.css b/axum_server/styles/input.css index cdc6dc5..db3f070 100644 --- a/axum_server/styles/input.css +++ b/axum_server/styles/input.css @@ -2,6 +2,14 @@ @tailwind components; @tailwind utilities; +a { + @apply text-pink-600 underline underline-offset-2; + + &:hover { + @apply transition text-blue-400; + } +} + .article-body { h1 { @apply px-4 text-2xl text-blue-900 my-2; diff --git a/axum_server/styles/output.css b/axum_server/styles/output.css index 06aa446..6d05424 100644 --- a/axum_server/styles/output.css +++ b/axum_server/styles/output.css @@ -562,16 +562,50 @@ video { margin: 1rem; } +.m-5 { + margin: 1.25rem; +} + +.mx-0 { + margin-left: 0px; + margin-right: 0px; +} + +.mx-0\.5 { + margin-left: 0.125rem; + margin-right: 0.125rem; +} + +.mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + .mx-4 { margin-left: 1rem; margin-right: 1rem; } +.mx-5 { + margin-left: 1.25rem; + margin-right: 1.25rem; +} + .mx-6 { margin-left: 1.5rem; margin-right: 1.5rem; } +.my-0 { + margin-top: 0px; + margin-bottom: 0px; +} + +.my-0\.5 { + margin-top: 0.125rem; + margin-bottom: 0.125rem; +} + .my-12 { margin-top: 3rem; margin-bottom: 3rem; @@ -587,16 +621,6 @@ video { margin-bottom: 1.5rem; } -.mx-2 { - margin-left: 0.5rem; - margin-right: 0.5rem; -} - -.my-2 { - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} - .mb-1 { margin-bottom: 0.25rem; } @@ -605,6 +629,10 @@ video { margin-bottom: 0.75rem; } +.mb-5 { + margin-bottom: 1.25rem; +} + .mt-3 { margin-top: 0.75rem; } @@ -613,6 +641,10 @@ video { display: block; } +.inline-block { + display: inline-block; +} + .inline { display: inline; } @@ -707,6 +739,11 @@ video { border-color: rgb(59 130 246 / var(--tw-border-opacity)); } +.border-blue-950 { + --tw-border-opacity: 1; + border-color: rgb(23 37 84 / var(--tw-border-opacity)); +} + .bg-blue-50 { --tw-bg-opacity: 1; background-color: rgb(239 246 255 / var(--tw-bg-opacity)); @@ -726,6 +763,14 @@ video { fill: #172554; } +.p-0 { + padding: 0px; +} + +.p-0\.5 { + padding: 0.125rem; +} + .p-3 { padding: 0.75rem; } @@ -740,16 +785,6 @@ video { padding-right: 1.25rem; } -.py-3 { - padding-top: 0.75rem; - padding-bottom: 0.75rem; -} - -.py-4 { - padding-top: 1rem; - padding-bottom: 1rem; -} - .py-5 { padding-top: 1.25rem; padding-bottom: 1.25rem; @@ -805,6 +840,10 @@ video { font-weight: 600; } +.capitalize { + text-transform: capitalize; +} + .italic { font-style: italic; } @@ -843,6 +882,11 @@ video { color: rgb(31 41 55 / var(--tw-text-opacity)); } +.text-pink-950 { + --tw-text-opacity: 1; + color: rgb(80 7 36 / var(--tw-text-opacity)); +} + .drop-shadow-md { --tw-drop-shadow: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06)); filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); @@ -858,6 +902,24 @@ video { transition-duration: 150ms; } +a { + --tw-text-opacity: 1; + color: rgb(219 39 119 / var(--tw-text-opacity)); + text-decoration-line: underline; + text-underline-offset: 2px; + &:hover { + --tw-text-opacity: 1; + color: rgb(96 165 250 / var(--tw-text-opacity)); + } + &:hover { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + } +} + .article-body { h1 { margin-top: 0.5rem; @@ -959,11 +1021,6 @@ video { margin: 1rem; } -.hover\:bg-blue-200:hover { - --tw-bg-opacity: 1; - background-color: rgb(191 219 254 / var(--tw-bg-opacity)); -} - .hover\:bg-pink-200:hover { --tw-bg-opacity: 1; background-color: rgb(251 207 232 / var(--tw-bg-opacity)); diff --git a/axum_server/templates/components/talent_card.html b/axum_server/templates/components/talent_card.html index 7e302c2..8a9df82 100644 --- a/axum_server/templates/components/talent_card.html +++ b/axum_server/templates/components/talent_card.html @@ -10,7 +10,7 @@

{{heading}}

-

{{description}}

+

{{description|safe}}

diff --git a/axum_server/templates/index.html b/axum_server/templates/index.html index 9301701..187771a 100644 --- a/axum_server/templates/index.html +++ b/axum_server/templates/index.html @@ -22,20 +22,38 @@

-

About me

+

About me

-

+

Welcome to my personal website. My name is Michal Vanko and I'm a programmer - . I am developing software for more than half of my life and I love it! Sometimes I stream working on my side projects and building a community of like minded people. Here you can find blogs of my thoughts and journeys, as well as links to my socials where you can see other content.

+ . I am developing software for more than half of my life and I love it! Sometimes I stream working on my side projects and building a community of like minded people. Here you can find blogs of my thoughts and journeys, as well as links to my socials where you can see other content.

-
+
{% call tc::talent_card("code", "Web development", "Extensive expertise in creating performant, live web applications and websites") %} {% call tc::talent_card("gamepad", "Game development", "Extensive expertise in creating performant, live web applications and websites") %} + {% call tc::talent_card("person-chalkboard", "Mentoring & Consulting", "I offer consulting sessions to assist you in developing higher-quality software and share insights from crafting robust, professional web applications. Schedule a session with me and elevate your projects together.") %}
+

Blog

+
+ +
+
+ +
    + +
+

Follow my twitch stream

diff --git a/axum_server/templates/site_header.html b/axum_server/templates/site_header.html index 5f7c220..3ebe213 100644 --- a/axum_server/templates/site_header.html +++ b/axum_server/templates/site_header.html @@ -1,4 +1,4 @@ -
+
+
diff --git a/src/svg/person-chalkboard.svg b/src/svg/person-chalkboard.svg new file mode 100644 index 0000000..23629a7 --- /dev/null +++ b/src/svg/person-chalkboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/svg/icons-sprite.svg b/static/svg/icons-sprite.svg index c050368..ed8d355 100644 --- a/static/svg/icons-sprite.svg +++ b/static/svg/icons-sprite.svg @@ -14,6 +14,6 @@ - + \ No newline at end of file