Compare commits
No commits in common. "2e47c91985e84bb950216934cca3e19355210b5e" and "e04e4f6491922bd0fcdfd5d6e3823b0fc8e60e32" have entirely different histories.
2e47c91985
...
e04e4f6491
@ -24,7 +24,7 @@
|
|||||||
@404 {
|
@404 {
|
||||||
expression {http.error.status_code} == 404
|
expression {http.error.status_code} == 404
|
||||||
}
|
}
|
||||||
rewrite @404 /not-found.html
|
rewrite @404 /404.html
|
||||||
file_server
|
file_server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
justfile
1
justfile
@ -52,7 +52,6 @@ clean:
|
|||||||
# SSG
|
# SSG
|
||||||
ssg:
|
ssg:
|
||||||
- wget --no-convert-links -r -p -E -P dist --no-host-directories 127.0.0.1:{{port}}
|
- wget --no-convert-links -r -p -E -P dist --no-host-directories 127.0.0.1:{{port}}
|
||||||
- wget --no-convert-links -p -E -P dist --no-host-directories 127.0.0.1:{{port}}/not-found
|
|
||||||
find generated_images/ -name "*_og*" -exec cp --parents {} dist/ \;
|
find generated_images/ -name "*_og*" -exec cp --parents {} dist/ \;
|
||||||
|
|
||||||
# Preview server
|
# Preview server
|
||||||
|
@ -1,23 +1,14 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::post_utils::post_parser::deserialize_date;
|
use crate::post_utils::post_parser::deserialize_date;
|
||||||
|
|
||||||
pub const BLOG_POST_PATH: &str = "_posts/blog";
|
pub const BLOG_POST_PATH: &str = "_posts/blog";
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
#[serde(rename_all = "lowercase")] // Optional, this converts enum variants to lowercase
|
|
||||||
pub enum Segment {
|
|
||||||
Blog,
|
|
||||||
Broadcasts,
|
|
||||||
Featured,
|
|
||||||
Cookbook,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct BlogPostMetadata {
|
pub struct BlogPostMetadata {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub segments: Vec<Segment>,
|
pub segments: Vec<String>,
|
||||||
pub published: bool,
|
pub published: bool,
|
||||||
#[serde(deserialize_with = "deserialize_date")]
|
#[serde(deserialize_with = "deserialize_date")]
|
||||||
pub date: DateTime<Utc>,
|
pub date: DateTime<Utc>,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use axum::{self};
|
use askama_axum::IntoResponse;
|
||||||
|
use axum::{self, extract::OriginalUri, http::StatusCode};
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use tower_livereload::LiveReloadLayer;
|
use tower_livereload::LiveReloadLayer;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
@ -56,5 +57,3 @@ async fn main() {
|
|||||||
// THINK deploy to alula? rather then katelyn? can be change whenever
|
// THINK deploy to alula? rather then katelyn? can be change whenever
|
||||||
//
|
//
|
||||||
// TODO 404 page
|
// TODO 404 page
|
||||||
// TODO view page transitions
|
|
||||||
// TODO cookbook
|
|
||||||
|
@ -6,11 +6,10 @@ use tokio::try_join;
|
|||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
blog_posts::blog_post_model::{BlogPostMetadata, Segment, BLOG_POST_PATH},
|
blog_posts::blog_post_model::{BlogPostMetadata, BLOG_POST_PATH},
|
||||||
components::site_header::{HeaderProps, Link},
|
components::site_header::{HeaderProps, Link},
|
||||||
post_utils::{
|
post_utils::{
|
||||||
post_listing::get_post_list,
|
post_listing::get_post_list,
|
||||||
segments::get_posts_by_segment,
|
|
||||||
tags::{get_popular_tags, get_posts_by_tag},
|
tags::{get_popular_tags, get_posts_by_tag},
|
||||||
},
|
},
|
||||||
projects::featured_projects::get_featured_projects,
|
projects::featured_projects::get_featured_projects,
|
||||||
@ -18,7 +17,6 @@ use crate::{
|
|||||||
|
|
||||||
use super::post_list::PostListTemplate;
|
use super::post_list::PostListTemplate;
|
||||||
|
|
||||||
// TODO Refactor to render post list for the same broadcasts, blog and cookbook
|
|
||||||
pub async fn render_blog_post_list(
|
pub async fn render_blog_post_list(
|
||||||
tag: Option<Path<String>>,
|
tag: Option<Path<String>>,
|
||||||
OriginalUri(original_uri): OriginalUri,
|
OriginalUri(original_uri): OriginalUri,
|
||||||
@ -26,14 +24,18 @@ pub async fn render_blog_post_list(
|
|||||||
// I will forget what happens here in a week. But essentially it's pattern matching and shadowing
|
// I will forget what happens here in a week. But essentially it's pattern matching and shadowing
|
||||||
let tag = tag.map(|Path(tag)| tag);
|
let tag = tag.map(|Path(tag)| tag);
|
||||||
|
|
||||||
let (blog_tags, featured_projects, post_list) = try_join!(
|
let (blog_tags, featured_projects, mut post_list) = try_join!(
|
||||||
get_popular_tags(Some(Segment::Blog)),
|
get_popular_tags(Some("blog".to_string())),
|
||||||
get_featured_projects(),
|
get_featured_projects(),
|
||||||
get_post_list::<BlogPostMetadata>(BLOG_POST_PATH)
|
get_post_list::<BlogPostMetadata>(BLOG_POST_PATH)
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let posts = get_posts_by_segment(post_list, &[Segment::Blog]);
|
post_list.sort_by_key(|post| post.metadata.date);
|
||||||
let posts = get_posts_by_tag(posts, &tag);
|
post_list.retain(|post| post.metadata.published);
|
||||||
|
post_list.retain(|post| post.metadata.segments.contains(&"blog".to_string()));
|
||||||
|
post_list.reverse();
|
||||||
|
|
||||||
|
let posts = get_posts_by_tag(post_list, &tag);
|
||||||
let header_props = match tag {
|
let header_props = match tag {
|
||||||
Some(_) => HeaderProps::with_back_link(Link {
|
Some(_) => HeaderProps::with_back_link(Link {
|
||||||
href: "/blog".to_string(),
|
href: "/blog".to_string(),
|
||||||
@ -53,7 +55,7 @@ pub async fn render_blog_post_list(
|
|||||||
Ok(PostListTemplate {
|
Ok(PostListTemplate {
|
||||||
title,
|
title,
|
||||||
og_title,
|
og_title,
|
||||||
segment: Segment::Blog,
|
segment: "blog".to_string(),
|
||||||
posts,
|
posts,
|
||||||
header_props,
|
header_props,
|
||||||
tags: blog_tags,
|
tags: blog_tags,
|
||||||
|
@ -6,11 +6,10 @@ use tokio::try_join;
|
|||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
blog_posts::blog_post_model::{BlogPostMetadata, Segment, BLOG_POST_PATH},
|
blog_posts::blog_post_model::{BlogPostMetadata, BLOG_POST_PATH},
|
||||||
components::site_header::{HeaderProps, Link},
|
components::site_header::{HeaderProps, Link},
|
||||||
post_utils::{
|
post_utils::{
|
||||||
post_listing::get_post_list,
|
post_listing::get_post_list,
|
||||||
segments::get_posts_by_segment,
|
|
||||||
tags::{get_popular_tags, get_posts_by_tag},
|
tags::{get_popular_tags, get_posts_by_tag},
|
||||||
},
|
},
|
||||||
projects::featured_projects::get_featured_projects,
|
projects::featured_projects::get_featured_projects,
|
||||||
@ -25,14 +24,18 @@ pub async fn render_broadcast_post_list(
|
|||||||
// I will forget what happens here in a week. But essentially it's pattern matching and shadowing
|
// I will forget what happens here in a week. But essentially it's pattern matching and shadowing
|
||||||
let tag = tag.map(|Path(tag)| tag);
|
let tag = tag.map(|Path(tag)| tag);
|
||||||
|
|
||||||
let (popular_tags, featured_projects, post_list) = try_join!(
|
let (popular_tags, featured_projects, mut post_list) = try_join!(
|
||||||
get_popular_tags(Some(Segment::Broadcasts)),
|
get_popular_tags(Some("broadcasts".to_string())),
|
||||||
get_featured_projects(),
|
get_featured_projects(),
|
||||||
get_post_list::<BlogPostMetadata>(BLOG_POST_PATH)
|
get_post_list::<BlogPostMetadata>(BLOG_POST_PATH)
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let posts = get_posts_by_segment(post_list, &[Segment::Broadcasts]);
|
post_list.sort_by_key(|post| post.metadata.date);
|
||||||
let posts = get_posts_by_tag(posts, &tag);
|
post_list.retain(|post| post.metadata.published);
|
||||||
|
post_list.retain(|post| post.metadata.segments.contains(&"broadcasts".to_string()));
|
||||||
|
post_list.reverse();
|
||||||
|
|
||||||
|
let posts = get_posts_by_tag(post_list, &tag);
|
||||||
|
|
||||||
let header_props = match tag {
|
let header_props = match tag {
|
||||||
Some(_) => HeaderProps::with_back_link(Link {
|
Some(_) => HeaderProps::with_back_link(Link {
|
||||||
@ -53,7 +56,7 @@ pub async fn render_broadcast_post_list(
|
|||||||
Ok(PostListTemplate {
|
Ok(PostListTemplate {
|
||||||
title: title.clone(),
|
title: title.clone(),
|
||||||
og_title: title,
|
og_title: title,
|
||||||
segment: Segment::Broadcasts,
|
segment: "broadcasts".to_string(),
|
||||||
posts,
|
posts,
|
||||||
header_props,
|
header_props,
|
||||||
tags: popular_tags,
|
tags: popular_tags,
|
||||||
|
@ -5,7 +5,7 @@ use axum::http::StatusCode;
|
|||||||
use tokio::try_join;
|
use tokio::try_join;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
blog_posts::blog_post_model::{BlogPostMetadata, Segment, BLOG_POST_PATH},
|
blog_posts::blog_post_model::{BlogPostMetadata, BLOG_POST_PATH},
|
||||||
components::site_header::HeaderProps,
|
components::site_header::HeaderProps,
|
||||||
filters,
|
filters,
|
||||||
post_utils::{
|
post_utils::{
|
||||||
@ -28,8 +28,8 @@ pub struct IndexTemplate {
|
|||||||
|
|
||||||
pub async fn render_index() -> Result<IndexTemplate, StatusCode> {
|
pub async fn render_index() -> Result<IndexTemplate, StatusCode> {
|
||||||
let (blog_tags, broadcasts_tags, all_posts, featured_projects) = try_join!(
|
let (blog_tags, broadcasts_tags, all_posts, featured_projects) = try_join!(
|
||||||
get_popular_tags(Some(Segment::Blog)),
|
get_popular_tags(Some("blog".to_string())),
|
||||||
get_popular_tags(Some(Segment::Broadcasts)),
|
get_popular_tags(Some("broadcasts".to_string())),
|
||||||
get_post_list::<BlogPostMetadata>(BLOG_POST_PATH),
|
get_post_list::<BlogPostMetadata>(BLOG_POST_PATH),
|
||||||
get_featured_projects()
|
get_featured_projects()
|
||||||
)?;
|
)?;
|
||||||
@ -39,10 +39,12 @@ pub async fn render_index() -> Result<IndexTemplate, StatusCode> {
|
|||||||
all_posts.into_iter().map(Rc::new).collect();
|
all_posts.into_iter().map(Rc::new).collect();
|
||||||
|
|
||||||
let featured_blog_posts =
|
let featured_blog_posts =
|
||||||
ref_get_posts_by_segment(&all_posts_rc, &[Segment::Blog, Segment::Featured]);
|
ref_get_posts_by_segment(&all_posts_rc, &["blog".to_string(), "featured".to_string()]);
|
||||||
|
|
||||||
let featured_broadcasts =
|
let featured_broadcasts = ref_get_posts_by_segment(
|
||||||
ref_get_posts_by_segment(&all_posts_rc, &[Segment::Broadcasts, Segment::Featured]);
|
&all_posts_rc,
|
||||||
|
&["broadcasts".to_string(), "featured".to_string()],
|
||||||
|
);
|
||||||
|
|
||||||
Ok(IndexTemplate {
|
Ok(IndexTemplate {
|
||||||
header_props: HeaderProps::default(),
|
header_props: HeaderProps::default(),
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
blog_posts::blog_post_model::{BlogPostMetadata, Segment},
|
blog_posts::blog_post_model::BlogPostMetadata, components::site_header::HeaderProps, filters,
|
||||||
components::site_header::HeaderProps,
|
post_utils::post_parser::ParseResult, projects::project_model::ProjectMetadata,
|
||||||
filters,
|
|
||||||
post_utils::post_parser::ParseResult,
|
|
||||||
projects::project_model::ProjectMetadata,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
@ -13,7 +10,7 @@ use crate::{
|
|||||||
pub struct PostListTemplate {
|
pub struct PostListTemplate {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub og_title: String,
|
pub og_title: String,
|
||||||
pub segment: Segment,
|
pub segment: String,
|
||||||
pub posts: Vec<ParseResult<BlogPostMetadata>>,
|
pub posts: Vec<ParseResult<BlogPostMetadata>>,
|
||||||
pub header_props: HeaderProps,
|
pub header_props: HeaderProps,
|
||||||
pub tags: Vec<String>,
|
pub tags: Vec<String>,
|
||||||
|
@ -1,50 +1,35 @@
|
|||||||
use std::{fmt::Display, rc::Rc};
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::blog_posts::blog_post_model::{BlogPostMetadata, Segment};
|
use crate::blog_posts::blog_post_model::BlogPostMetadata;
|
||||||
|
|
||||||
use super::post_parser::ParseResult;
|
use super::post_parser::ParseResult;
|
||||||
|
|
||||||
impl Segment {
|
// // TODO convert segmetns to enum, find out how to serde to enum vlaue
|
||||||
fn as_str(&self) -> &'static str {
|
// pub fn get_posts_by_segment(
|
||||||
match self {
|
// post_list: &Vec<ParseResult<BlogPostMetadata>>,
|
||||||
Segment::Blog => "blog",
|
// segments: &Vec<String>,
|
||||||
Segment::Broadcasts => "broadcasts",
|
// ) -> Vec<ParseResult<BlogPostMetadata>> {
|
||||||
Segment::Featured => "featured",
|
// let mut filtered_posts: Vec<ParseResult<BlogPostMetadata>> = post_list
|
||||||
Segment::Cookbook => "cookbook",
|
// .iter()
|
||||||
}
|
// .filter(|post| {
|
||||||
}
|
// segments
|
||||||
}
|
// .iter()
|
||||||
|
// .all(|segment| post.metadata.segments.contains(segment))
|
||||||
|
// }) // Filter by segments
|
||||||
|
// .filter(|post| post.metadata.published) // Filter only published posts
|
||||||
|
// .cloned()
|
||||||
|
// .collect();
|
||||||
|
|
||||||
impl Display for Segment {
|
// // Sort by date in descending order
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
// filtered_posts.sort_by_key(|post| post.metadata.date);
|
||||||
write!(f, "{}", self.as_str())
|
// filtered_posts.reverse();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_posts_by_segment(
|
// filtered_posts
|
||||||
post_list: Vec<ParseResult<BlogPostMetadata>>,
|
// }
|
||||||
segments: &[Segment],
|
|
||||||
) -> Vec<ParseResult<BlogPostMetadata>> {
|
|
||||||
let mut filtered_posts: Vec<ParseResult<BlogPostMetadata>> = post_list
|
|
||||||
.into_iter()
|
|
||||||
.filter(|post| {
|
|
||||||
segments
|
|
||||||
.iter()
|
|
||||||
.all(|segment| post.metadata.segments.contains(segment))
|
|
||||||
}) // Filter by segments
|
|
||||||
.filter(|post| post.metadata.published) // Filter only published posts
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Sort by date in descending order
|
|
||||||
filtered_posts.sort_by_key(|post| post.metadata.date);
|
|
||||||
filtered_posts.reverse();
|
|
||||||
|
|
||||||
filtered_posts
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ref_get_posts_by_segment(
|
pub fn ref_get_posts_by_segment(
|
||||||
post_list: &[Rc<ParseResult<BlogPostMetadata>>],
|
post_list: &[Rc<ParseResult<BlogPostMetadata>>],
|
||||||
segments: &[Segment],
|
segments: &[String],
|
||||||
) -> Vec<Rc<ParseResult<BlogPostMetadata>>> {
|
) -> Vec<Rc<ParseResult<BlogPostMetadata>>> {
|
||||||
let mut filtered_posts: Vec<Rc<ParseResult<BlogPostMetadata>>> = post_list
|
let mut filtered_posts: Vec<Rc<ParseResult<BlogPostMetadata>>> = post_list
|
||||||
.iter() // Use iter() to borrow instead of consuming the original vector
|
.iter() // Use iter() to borrow instead of consuming the original vector
|
||||||
|
@ -2,11 +2,11 @@ use axum::http::StatusCode;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::blog_posts::blog_post_model::{BlogPostMetadata, Segment, BLOG_POST_PATH};
|
use crate::blog_posts::blog_post_model::{BlogPostMetadata, BLOG_POST_PATH};
|
||||||
|
|
||||||
use super::{post_listing::get_post_list, post_parser::ParseResult};
|
use super::{post_listing::get_post_list, post_parser::ParseResult};
|
||||||
|
|
||||||
pub async fn get_popular_tags(segment: Option<Segment>) -> Result<Vec<String>, StatusCode> {
|
pub async fn get_popular_tags(segment: Option<String>) -> Result<Vec<String>, StatusCode> {
|
||||||
const TAGS_LENGTH: usize = 7;
|
const TAGS_LENGTH: usize = 7;
|
||||||
|
|
||||||
let mut post_list = get_post_list::<BlogPostMetadata>(BLOG_POST_PATH).await?;
|
let mut post_list = get_post_list::<BlogPostMetadata>(BLOG_POST_PATH).await?;
|
||||||
|
Loading…
Reference in New Issue
Block a user