diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 213 |
1 files changed, 14 insertions, 199 deletions
diff --git a/src/main.rs b/src/main.rs index 7b5ddfc..fb15e51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,199 +1,14 @@ -use std::cmp::Ordering; -use std::borrow::Cow; -use tower_http::services::ServeDir; -use axum::response::Html; -use axum::extract::State; -use std::sync::Arc; -use askama_axum::Template; use axum::{routing::get, Router}; -use std::fmt; -use std::fs; -use std::path::PathBuf; -use chrono::Datelike; - -fn current_year() -> i32 { - chrono::Utc::now().year() -} - -trait Post: fmt::Debug { - fn get_title(&self) -> &str; - fn get_article(&self) -> Cow<str>; -} - -#[derive(Debug)] -struct FsPost { - file: PathBuf, -} - -impl Post for FsPost { - fn get_title(&self) -> &str { - self.file.file_name().unwrap().to_str().unwrap() - } - - fn get_article(&self) -> Cow<str> { - let article = fs::read_to_string(&self.file).unwrap(); - Cow::Owned(article) - } -} - -trait PostRepo { - fn load(&self) -> impl IntoIterator<Item = impl Post>; -} - -struct FsPostRepo { - dir: PathBuf, -} - -impl FsPostRepo { - fn with_dir(path: impl Into<PathBuf>) -> Self { - Self { - dir: path.into() - } - } -} - -impl PostRepo for FsPostRepo { - fn load(&self) -> impl IntoIterator<Item = FsPost> { - let files = fs::read_dir(&self.dir).unwrap(); - files - .flatten() - .filter(|d| !d.file_name().to_string_lossy().starts_with('.')) - .map(|d| FsPost { file: d.path() }) - } -} - - -#[derive(Template)] -#[template(path = "posts.html")] -struct PostsView<P: Post> { - posts: Vec<P> -} - -impl<P: Post> PostsView<P> { - fn with_posts(posts: impl IntoIterator<Item = P>) -> Self { - Self { - posts: posts.into_iter().collect() - } - } -} - -async fn posts_handler(State(repo): State<Arc<impl PostRepo>>) -> Html<String> { - let view = PostsView::with_posts(repo.load()); - Html(view.render().unwrap()) -} - -trait Tutor: fmt::Debug + Ord { - fn get_name(&self) -> &str; - fn get_id(&self) -> &str; - fn get_blurb(&self) -> Cow<str>; -} - -#[derive(Debug, Eq)] -struct FsTutor { - dir: PathBuf -} - -impl Tutor for FsTutor { - fn get_id(&self) -> &str { - self.dir.file_name().unwrap().to_str().unwrap() - } - - fn get_name(&self) -> &str { - self.get_id() - } - - fn get_blurb(&self) -> Cow<str> { - let mut path = self.dir.to_owned(); - path.push(format!("{}.md", self.get_id())); - let blurb = fs::read_to_string(path).unwrap(); - Cow::Owned(blurb) - } -} - -impl Ord for FsTutor { - fn cmp(&self, other: &Self) -> Ordering { - self.get_id().cmp(other.get_id()) - } -} - -impl PartialOrd for FsTutor { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl PartialEq for FsTutor { - fn eq(&self, other: &Self) -> bool { - self.get_id() == other.get_id() - } -} - -trait TutorRepo { - fn load(&self) -> impl IntoIterator<Item = impl Tutor>; -} - -struct FsTutorRepo { - dir: PathBuf -} - -impl FsTutorRepo { - fn with_dir(path: impl Into<PathBuf>) -> Self { - Self { - dir: path.into() - } - } -} - - -impl TutorRepo for FsTutorRepo { - fn load(&self) -> impl IntoIterator<Item = FsTutor> { - let dirs = fs::read_dir(&self.dir).unwrap(); - dirs.flatten().filter(|d| !d.path().file_stem().unwrap().to_str().unwrap_or_default().starts_with('.')).map(|d| FsTutor { dir: d.path() }) - } -} - - -#[derive(Template)] -#[template(path = "about/index.html")] -struct AboutView<T: Tutor> { - tutors: Vec<T>, -} -impl<T: Tutor + Ord> AboutView<T> { - fn with_tutors(tutors: impl IntoIterator<Item = T>) -> Self { - let mut tutors: Vec<T> = tutors.into_iter().collect(); - tutors.sort(); - Self { tutors } - } -} - -async fn about_handler(State(repo): State<Arc<impl TutorRepo>>) -> Html<String> { - let view = AboutView::with_tutors(repo.load()); - Html(view.render().unwrap()) -} - -#[derive(Template)] -#[template(path = "index.html")] -struct IndexTemplate; - -async fn index_handler() -> Html<String> { - Html(IndexTemplate {}.render().unwrap()) -} - -#[derive(Template)] -#[template(path = "policies.html")] -struct PoliciesTemplate; - -async fn policies_handler() -> Html<String> { - Html(PoliciesTemplate{}.render().unwrap()) -} - -#[derive(Template)] -#[template(path = "brochure/index.html")] -struct BrochureTemplate; +use tutors::fs_tutor_repo::FsTutorRepo; +use std::sync::Arc; +use tower_http::services::ServeDir; +use posts::fs_post_repo::FsPostRepo; -async fn brochure_handler() -> Html<String> { - Html(BrochureTemplate{}.render().unwrap()) -} +mod helpers; +mod posts; +mod tutors; +mod views; +mod handlers; #[tokio::main] async fn main() { @@ -201,12 +16,12 @@ async fn main() { let tutors = Arc::new(FsTutorRepo::with_dir(format!("/data/ct/{}", "team"))); let app = Router::new() - .route("/", get(index_handler)) - .route("/posts", get(posts_handler)) + .route("/", get(handlers::index_handler)) + .route("/posts", get(handlers::posts_handler)) .with_state(posts) - .route("/policies", get(policies_handler)) - .route("/brochure", get(brochure_handler)) - .route("/about", get(about_handler)) + .route("/policies", get(handlers::policies_handler)) + .route("/brochure", get(handlers::brochure_handler)) + .route("/about", get(handlers::about_handler)) .with_state(tutors) .nest_service("/assets", ServeDir::new("/data/ct/assets")) .nest_service("/team", ServeDir::new("/data/ct/team")) |