Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
website.rs 4.92 KiB
Newer Older
  • Learn to ignore specific revisions
  • use super::page::{Page, PageTemplate};
    
    peterrabbit's avatar
    peterrabbit committed
    use crate::app::AppConfig;
    
    use crate::static_files::StaticFilesManager;
    
    use serde::ser::{SerializeStruct, Serializer};
    
    peterrabbit's avatar
    peterrabbit committed
    use serde::{Deserialize, Serialize};
    
    use std::io::prelude::*;
    
    peterrabbit's avatar
    peterrabbit committed
    use std::path::PathBuf;
    
    peterrabbit's avatar
    peterrabbit committed
    
    #[derive(Debug, Serialize, Deserialize, Clone)]
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
    pub struct WebSiteData {
    
        root_page: Page,
        #[serde(default = "Vec::new")]
        assets_index: Vec<String>,
        templates: Vec<PageTemplate>,
    }
    
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
    pub struct WebSiteBuilder(WebSiteData);
    
    
    peterrabbit's avatar
    peterrabbit committed
    pub struct WebSite {
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
        last_generated_page_id: usize,
    
    peterrabbit's avatar
    peterrabbit committed
        root_page: Page,
    
        pub static_files_manager: StaticFilesManager,
    
    peterrabbit's avatar
    peterrabbit committed
        templates: Vec<PageTemplate>,
    
    peterrabbit's avatar
    peterrabbit committed
    }
    
    
    impl Serialize for WebSite {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            let mut state = serializer.serialize_struct("WebSite", 3)?;
            state.serialize_field("root_page", &self.root_page)?;
            state.serialize_field("templates", &self.templates)?;
            state.serialize_field("assets_index", &self.static_files_manager.index)?;
            state.end()
        }
    }
    
    
    impl WebSiteBuilder {
        pub fn with_static_files_manager(
            &mut self,
            static_files_manager: StaticFilesManager,
        ) -> WebSite {
            WebSite {
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                last_generated_page_id: 0,
                root_page: self.0.root_page.clone(),
    
                static_files_manager: {
                    let mut static_files_manager = static_files_manager;
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                    static_files_manager.add_assets_pathes(&self.0.assets_index);
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                templates: self.0.templates.clone(),
    
    peterrabbit's avatar
    peterrabbit committed
            }
        }
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
        pub fn from_json(json: &str) -> Self {
            WebSiteBuilder(serde_json::from_str(json).unwrap())
        }
    
    
        #[cfg(test)]
        pub fn testing(test_dir: &PathBuf) -> WebSite {
            Self::from_json(crate::testing::TEST_JSON_WEBSITE)
                .with_static_files_manager(StaticFilesManager::testing_new(test_dir).unwrap())
        }
    
    
        fn blank_website_template() -> PathBuf {
            std::env::current_dir()
                .unwrap()
                .join("templates")
                .join("new_website.json")
        }
    
        pub fn load(config: &AppConfig) -> Self {
    
            let file_path = match &config.load {
                Some(pth) => pth.clone(),
    
                None => {
                    if let Some(loaded) = Self::try_load_from_existing_file(config) {
                        return loaded;
                    }
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
    
    
                    Self::blank_website_template()
                }
    
            Self::from_json(&std::fs::read_to_string(file_path).unwrap())
        }
    
        fn try_load_from_existing_file(config: &AppConfig) -> Option<Self> {
            let website_file_path = config.storage_dir.join("website.json");
    
            if website_file_path.exists() {
                match &std::fs::read_to_string(&website_file_path) {
                    Ok(json) => return Some(Self::from_json(&json)),
                    Err(_) => return None,
                }
            }
    
            None
        }
    
    peterrabbit's avatar
    peterrabbit committed
    impl WebSite {
    
        pub fn build(&mut self) -> Result<Self, String> {
            if let Err(err) = self.root_page.build(
    
                &self.templates,
                PathBuf::from("/"),
                &self.static_files_manager,
    
            ) {
                return Err(err);
            };
    
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
            self.generate_pages_ids();
    
    
            Ok(self.clone())
    
    peterrabbit's avatar
    peterrabbit committed
        }
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
        fn init_last_generated_page_id(&mut self) {
            let mut ids = vec![self.root_page.get_id()];
    
            fn collect_ids(p: &Page, ids: &mut Vec<usize>) {
                for sp in p.sub_pages.iter() {
                    ids.push(sp.get_id());
                    collect_ids(sp, ids);
                }
            }
    
            collect_ids(&self.root_page, &mut ids);
    
            self.last_generated_page_id = *ids.iter().max().unwrap();
        }
    
        fn generate_pages_ids(&mut self) {
            self.init_last_generated_page_id();
    
            fn generate_page_id(page: &mut Page, last_generated_page_id: &mut usize) {
                if page.get_id() == 0 {
                    *last_generated_page_id += 1;
                    page.set_id(*last_generated_page_id);
                }
            }
    
            fn rec_gen_ids(
                p: &mut Page,
                gen_id: fn(&mut Page, &mut usize),
                last_generated_page_id: &mut usize,
            ) {
                gen_id(p, last_generated_page_id);
                for sp in p.sub_pages.iter_mut() {
                    rec_gen_ids(sp, gen_id, last_generated_page_id)
                }
            }
    
            rec_gen_ids(
                &mut self.root_page,
                generate_page_id,
                &mut self.last_generated_page_id,
            );
        }
    
    
        pub fn save(&self, config: &AppConfig) -> std::io::Result<()> {
            let save_json = serde_json::to_string(self).unwrap();
            let json_path = config.storage_dir.join("website.json");
            let mut f = std::fs::OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(&json_path)?;
    
            f.write_all(save_json.as_bytes())?;
            f.flush()?;
    
            Ok(())
        }