diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 110 |
1 files changed, 100 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs index ca0a3d9..d07d201 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,11 @@ use std::fs; use std::io::*; use std::path::Path; use std::path::PathBuf; +use chrono::Datelike; + +fn current_year() -> i32 { + chrono::Utc::now().year() +} trait Post: fmt::Debug { fn dump(&self); @@ -18,6 +23,12 @@ trait Post: fmt::Debug { fn get_content(&self) -> Cow<str>; } +trait Tutor: fmt::Debug { + fn id(&self) -> &str; + fn display_name(&self) -> &str; + fn blurb(&self) -> &str; +} + struct MdFilePost { path: PathBuf, name: OsString, @@ -56,7 +67,11 @@ impl fmt::Debug for MdFilePost { } trait Posts { - fn get_posts(&self) -> impl Iterator<Item = impl Post>; + fn get_posts(&self) -> impl IntoIterator<Item = impl Post>; +} + +trait Tutors { + fn get_tutors(&self) -> impl IntoIterator<Item = impl Tutor>; } struct FsDirPosts { @@ -71,10 +86,29 @@ impl FsDirPosts { } } +struct FsDirTutors { + path: PathBuf, +} + +impl Tutors for FsDirTutors { + fn get_tutors(&self) -> impl IntoIterator<Item = impl Tutor> { + let test: Vec<MdTutor> = Vec::new(); + test + } +} + +impl FsDirTutors { + fn new(path: &str) -> Self { + Self { + path: PathBuf::from(path), + } + } +} + impl Posts for FsDirPosts { - fn get_posts(&self) -> impl Iterator<Item = impl Post> { - let dirs = fs::read_dir(&self.path).unwrap(); - dirs.flatten().map(|d| MdFilePost::new(&d.path())) + fn get_posts(&self) -> impl IntoIterator<Item = impl Post> { + let files = fs::read_dir(&self.path).unwrap(); + files.flatten().filter(|d| !d.path().file_stem().unwrap().to_str().unwrap_or_default().starts_with('.')).map(|d| MdFilePost::new(&d.path())) } } @@ -105,16 +139,59 @@ struct PostsView { impl PostsView { fn with_posts(posts: &impl Posts) -> Self { Self { - post_titles: posts.get_posts().map(|p| p.display_name().into_owned()).map(String::from).collect() + post_titles: posts.get_posts().into_iter().map(|p| p.display_name().into_owned()).map(String::from).collect() } } } +// TODO: one single Markdown struct with id, name, and content can take over for both MdTutor and +// MdPost if it implements the Tutor and Post traits +// With this, I could have a repo which does all the same loading but returns things of a generic T +// as long as that T is provided it'll map values into those fields? + async fn posts_handler(State(posts): State<Arc<impl Posts>>) -> Html<String> { let view = PostsView::with_posts(&*posts); Html(view.render().unwrap()) } +#[derive(Debug)] +struct MdTutor { + id: String, + name: String, + blurb: String, +} + +impl Tutor for MdTutor { + fn id(&self) -> &str { + self.id.as_str() + } + + fn display_name(&self) -> &str { + self.name.as_str() + } + + fn blurb(&self) -> &str { + self.blurb.as_str() + } +} + +#[derive(Template)] +#[template(path = "about/index.html")] +struct AboutView<T: Tutor> { + tutors: Vec<T>, +} + +impl<T: Tutor> AboutView<T> { + fn with_tutors(tutors: &impl Tutors) -> Self { + todo!() + } +} + +async fn about_handler(State(tutors): State<Arc<impl Tutors>>) -> Html<String> { + let view: AboutView<MdTutor> = AboutView::with_tutors(&*tutors); + Html(view.render().unwrap()) +} + #[derive(Template)] #[template(path = "index.html")] struct IndexTemplate; @@ -131,17 +208,30 @@ async fn policies_handler() -> Html<String> { Html(PoliciesTemplate{}.render().unwrap()) } +#[derive(Template)] +#[template(path = "brochure/index.html")] +struct BrochureTemplate; + +async fn brochure_handler() -> Html<String> { + Html(BrochureTemplate{}.render().unwrap()) +} + #[tokio::main] async fn main() { - let repo = Arc::new(FsDirPosts::new(&format!("/data/ct/{}", "blog"))); + let posts = Arc::new(FsDirPosts::new(&format!("/data/ct/{}", "blog"))); + let tutors = Arc::new(FsDirTutors::new(&format!("/data/ct/{}", "team"))); let app = Router::new() - .nest_service("/static", ServeDir::new("static")) - .nest_service("/assets", ServeDir::new("/data/ct/assets")) + .route("/", get(index_handler)) .route("/posts", get(posts_handler)) + .with_state(posts) .route("/policies", get(policies_handler)) - .route("/", get(index_handler)) - .with_state(repo); + .route("/brochure", get(brochure_handler)) + .route("/about", get(about_handler)) + .with_state(tutors) + .nest_service("/assets", ServeDir::new("/data/ct/assets")) + .nest_service("/team", ServeDir::new("/data/ct/team")) + .fallback_service(ServeDir::new("static")); let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap(); axum::serve(listener, app).await.unwrap(); |