summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs213
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"))