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 3.54 KiB
use super::page::{Page, PageTemplate};
use crate::app::AppConfig;
use crate::static_files::StaticFilesManager;
use serde::ser::{SerializeStruct, Serializer};
use serde::{Deserialize, Serialize};
use std::io::prelude::*;
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,
    pub static_files_manager: StaticFilesManager,
    templates: Vec<PageTemplate>,
}

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 from_json(json: &str) -> Self {
        serde_json::from_str(json).unwrap()
    }

    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_assets_pathes(&self.assets_index);
                static_files_manager
            },
            templates: self.templates.clone(),
        }
    }

    #[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;
                }
                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
    }
}

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);
        };

        Ok(self.clone())
    }

    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(())
    }
}