From 59927adbd4c2a6cdcd55d1ed8899449a62f32e10 Mon Sep 17 00:00:00 2001
From: peterrabbit <pierre.jarriges@tutanota.com>
Date: Sun, 4 Sep 2022 10:36:45 +0200
Subject: [PATCH] WebSiteBuilder & WebSite::StaticFilesManager inner field

---
 README.md              |  24 +++-------
 example.json           |  24 +++-------
 src/main.rs            |  12 ++---
 src/service/page.rs    |   2 +-
 src/static_files.rs    |   9 +++-
 src/testing.rs         |   7 ---
 src/website/page.rs    |   5 +-
 src/website/website.rs | 106 ++++++++++++++++++++++-------------------
 8 files changed, 84 insertions(+), 105 deletions(-)

diff --git a/README.md b/README.md
index 95a4ac6..54f1df5 100644
--- a/README.md
+++ b/README.md
@@ -108,22 +108,12 @@ A website data is store as a JSON file with the following structure
             ]
         }
     ],
-    "assets_index": {
-        "images": [
-            "/static/images/toto.jpg"
-        ],
-        "sounds": [
-            "/static/sounds/toto.mp3"
-        ],
-        "video": [
-            "/static/video/toto.mp4"
-        ],
-        "docs": [
-            "/static/docs/toto.xcf"
-        ],
-        "source_code": [
-            "/static/source_code/toto.js"
-        ]
-    }
+    "assets_index": [
+        "/static/images/toto.jpg",
+        "/static/sounds/toto.mp3",
+        "/static/video/toto.mp4",
+        "/static/docs/toto.xcf",
+        "/static/source_code/toto.js"
+    ]
 }
 ```
\ No newline at end of file
diff --git a/example.json b/example.json
index d74a158..01cab40 100644
--- a/example.json
+++ b/example.json
@@ -72,21 +72,11 @@
             ]
         }
     ],
-    "assets_index": {
-        "images": [
-            "/static/images/toto.jpg"
-        ],
-        "sounds": [
-            "/static/sounds/toto.mp3"
-        ],
-        "video": [
-            "/static/video/toto.mp4"
-        ],
-        "docs": [
-            "/static/docs/toto.xcf"
-        ],
-        "source_code": [
-            "/static/source_code/toto.js"
-        ]
-    }
+    "assets_index": [
+        "/static/images/toto.jpg",
+        "/static/sounds/toto.mp3",
+        "/static/video/toto.mp4",
+        "/static/docs/toto.xcf",
+        "/static/source_code/toto.js"
+    ]
 }
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index c05f55e..ab89dc2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,7 +10,7 @@ use actix_web_lab::middleware::RedirectHttps;
 use app::AppState;
 use static_files::StaticFilesManager;
 use tls_config::tls_config;
-use website::WebSite;
+use website::WebSiteBuilder;
 
 #[actix_web::main]
 async fn main() -> std::io::Result<()> {
@@ -21,17 +21,16 @@ async fn main() -> std::io::Result<()> {
     )
     .init();
 
-    let website = WebSite::load(&app_state.config);
-    let mut static_files_manager = StaticFilesManager::new(&app_state).unwrap();
-    static_files_manager.build_index();
+    let website = WebSiteBuilder::load(&app_state.config)
+        .with_static_files_manager(StaticFilesManager::new(&app_state).unwrap().build())
+        .build();
 
     let host = app_state.config.host.clone();
     let port = app_state.config.port;
     let port_tls = app_state.config.port_tls;
 
     let srv_conf = tls_config(&app_state.config);
-    let static_dir = static_files_manager.dir.clone();
-    let mut_static_files_manager = web::Data::new(std::sync::Mutex::new(static_files_manager));
+    let static_dir = website.static_files_manager.dir.clone();
 
     let app_state = web::Data::new(std::sync::Mutex::new(app_state));
 
@@ -43,7 +42,6 @@ async fn main() -> std::io::Result<()> {
             .wrap(actix_web::middleware::Compress::default())
             .wrap(RedirectHttps::default().to_port(port_tls))
             .app_data(web::Data::clone(&app_state))
-            .app_data(web::Data::clone(&mut_static_files_manager))
             .app_data(web::Data::clone(&mut_website))
             .service(Files::new("/static/", &static_dir))
             .service(service::files::favicon)
diff --git a/src/service/page.rs b/src/service/page.rs
index c70a9ef..c0bfe7f 100644
--- a/src/service/page.rs
+++ b/src/service/page.rs
@@ -1,4 +1,4 @@
-use crate::WebSite;
+use crate::website::WebSite;
 use actix_web::{get, web, HttpResponse, Responder};
 use std::path::PathBuf;
 
diff --git a/src/static_files.rs b/src/static_files.rs
index dba9006..a8364f2 100644
--- a/src/static_files.rs
+++ b/src/static_files.rs
@@ -1,7 +1,7 @@
 use crate::app::AppState;
 use std::path::{Path, PathBuf};
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct StaticFilesManager {
     pub dir: PathBuf,
     pub index: Vec<String>,
@@ -69,8 +69,13 @@ impl StaticFilesManager {
             .push(format!("/{}", push_path.to_str().unwrap().to_owned()));
     }
 
-    pub fn build_index(&mut self) {
+    pub fn add_pathes(&mut self, pathes: &Vec<String>) {
+        self.index.extend(pathes.iter().map(|p| p.to_owned()));
+    }
+
+    pub fn build(&mut self) -> Self {
         self.index = Vec::new();
         self.rec_read_dir(&self.dir.clone(), &self.dir.clone());
+        self.clone()
     }
 }
diff --git a/src/testing.rs b/src/testing.rs
index c24e7ab..d4bd942 100644
--- a/src/testing.rs
+++ b/src/testing.rs
@@ -59,13 +59,6 @@ pub const TEST_JSON_WEBSITE: &'static str = "
             }
         ]
     },
-    \"assets_index\": {
-        \"images\": [],
-        \"sounds\": [],
-        \"videos\": [],
-        \"docs\": [],
-        \"source_code\": []
-    },
     \"templates\": [
         {
             \"name\": \"TEST TEMPLATE\",
diff --git a/src/website/page.rs b/src/website/page.rs
index 95ff31e..c8a2029 100644
--- a/src/website/page.rs
+++ b/src/website/page.rs
@@ -261,9 +261,6 @@ mod test_pages {
                         .0
                         .insert(String::from("id"), String::from("test-template"));
                     attrs
-                        .0
-                        .insert(String::from("class"), String::from("page-template"));
-                    attrs
                 },
                 contents: Some(vec![
                     HtmlElement {
@@ -381,7 +378,7 @@ mod test_pages {
         page.build_with_template(test_page_template());
         assert_eq!(
             page.body.to_string(),
-            "<div id=\"test-template\" class=\"page-template\"><nav>NAV</nav><div id=\"page-body\"><span>TEST</span></div><footer>FOOTER</footer></div>"
+            "<div id=\"test-template\"><nav>NAV</nav><div id=\"page-body\"><span>TEST</span></div><footer>FOOTER</footer></div>"
         )
     }
 }
diff --git a/src/website/website.rs b/src/website/website.rs
index dca24e6..ff97658 100644
--- a/src/website/website.rs
+++ b/src/website/website.rs
@@ -1,57 +1,75 @@
+use super::page::{Page, PageTemplate};
 use crate::app::AppConfig;
-use crate::website::page::{Page, PageTemplate};
+use crate::static_files::StaticFilesManager;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 use std::path::PathBuf;
 
 #[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct WebSiteBuilder {
+    root_page: Page,
+    #[serde(default = "Vec::new")]
+    assets_index: Vec<String>,
+    templates: Vec<PageTemplate>,
+}
+
+#[derive(Debug, Clone)]
 pub struct WebSite {
     root_page: Page,
-    #[serde(default = "AssetsIndex::new")]
-    assets_index: AssetsIndex,
+    pub static_files_manager: StaticFilesManager,
     templates: Vec<PageTemplate>,
-    #[serde(default = "HashMap::new")]
     pages_index: HashMap<PathBuf, Page>,
 }
 
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct AssetsIndex {
-    pub images: Vec<String>,
-    pub sounds: Vec<String>,
-    pub videos: Vec<String>,
-    pub docs: Vec<String>,
-    pub source_code: Vec<String>,
-}
+impl WebSiteBuilder {
+    pub fn from_json(json: &str) -> Self {
+        serde_json::from_str(json).unwrap()
+    }
 
-impl AssetsIndex {
-    pub fn new() -> Self {
-        AssetsIndex {
-            images: Vec::new(),
-            sounds: Vec::new(),
-            videos: Vec::new(),
-            docs: Vec::new(),
-            source_code: Vec::new(),
+    pub fn with_static_files_manager(
+        &mut self,
+        static_files_manager: StaticFilesManager,
+    ) -> WebSite {
+        WebSite {
+            root_page: self.root_page.clone(),
+            static_files_manager: {
+                let mut static_files_manager = static_files_manager;
+                static_files_manager.add_pathes(&self.assets_index);
+                static_files_manager
+            },
+            templates: self.templates.clone(),
+            pages_index: HashMap::new(),
         }
     }
+
+    pub fn load(config: &AppConfig) -> WebSiteBuilder {
+        let file_path = match &config.load {
+            None => std::env::current_dir()
+                .unwrap()
+                .join("templates")
+                .join("new_website.json"),
+            Some(pth) => pth.clone(),
+        };
+
+        WebSiteBuilder::from_json(&std::fs::read_to_string(file_path).unwrap())
+    }
 }
 
 impl WebSite {
-    pub fn from_json(json: &str) -> Self {
-        let mut obj: WebSite = serde_json::from_str(json).unwrap();
-
-        obj.root_page.build_with_template(
-            obj.templates
+    pub fn build(&mut self) -> Self {
+        self.root_page.build_with_template(
+            self.templates
                 .iter()
-                .find(|t| t.name == obj.root_page.template_name)
+                .find(|t| t.name == self.root_page.template_name)
                 .expect("Page template not found")
                 .clone(),
         );
 
-        obj.root_page.build_html();
+        self.root_page.build_html();
 
-        for p in obj.root_page.sub_pages.iter_mut() {
+        for p in self.root_page.sub_pages.iter_mut() {
             p.build_with_template(
-                obj.templates
+                self.templates
                     .iter()
                     .find(|t| t.name == p.template_name)
                     .expect("Page template not found")
@@ -60,22 +78,8 @@ impl WebSite {
             p.build_html();
         }
 
-        obj.build_assets_index();
-        obj.build_pages_index(obj.root_page.clone(), PathBuf::from("/"));
-
-        obj
-    }
-
-    pub fn load(config: &AppConfig) -> WebSite {
-        let file_path = match &config.load {
-            None => std::env::current_dir()
-                .unwrap()
-                .join("templates")
-                .join("new_website.json"),
-            Some(pth) => pth.clone(),
-        };
-
-        WebSite::from_json(&std::fs::read_to_string(file_path).unwrap())
+        self.build_pages_index(self.root_page.clone(), PathBuf::from("/"));
+        self.clone()
     }
 
     fn build_pages_index(&mut self, root_page: Page, from_url: PathBuf) {
@@ -88,10 +92,6 @@ impl WebSite {
         }
     }
 
-    fn build_assets_index(&mut self) {
-        return;
-    }
-
     pub fn get_page_by_url(&self, url: &PathBuf) -> Option<&Page> {
         self.pages_index.get(&PathBuf::from("/").join(url))
     }
@@ -104,7 +104,13 @@ mod test_website {
 
     #[test]
     fn test_index_pages_by_slug() {
-        let website = WebSite::from_json(TEST_JSON_WEBSITE);
+        let website = WebSiteBuilder::from_json(TEST_JSON_WEBSITE)
+            .with_static_files_manager(StaticFilesManager {
+                dir: PathBuf::from("."),
+                index: Vec::new(),
+            })
+            .build();
+
         let root_page = website.get_page_by_url(&PathBuf::from("/"));
         assert!(root_page.is_some());
         assert_eq!(root_page.unwrap().metadata.title, "TEST");
-- 
GitLab