//! All HTML templates. use { askama::Template, async_std::{ fs::{read_to_string, write}, path::PathBuf, }, chrono::NaiveDate, color_eyre::Result, }; use async_std::fs::create_dir_all; use crate::{ group_data::GroupDataModel, utilities::{get_base_url, today}, }; /// The template for the home page. #[derive(Template)] #[template(path = "index.html")] pub struct HomeTemplate { /// The base URL for links to the Tildes instance. pub base_url: String, /// Extra HTML to insert in the body. pub extra_body_html: String, /// Extra HTML to insert in the head. pub extra_head_html: String, /// The groups to create the table with. pub groups: Vec, /// The string for the `` element. pub page_title: String, /// The date of today's snapshot. pub today: NaiveDate, /// The user count from the group with the most subscribers. pub user_count: i64, } impl HomeTemplate { /// Create a new [`HomeTemplate`]. pub async fn new( groups: Vec<GroupDataModel>, user_count: Option<i64>, ) -> Self { let extra_body_html = read_to_string("extra-body.html").await; let extra_head_html = read_to_string("extra-head.html").await; Self { base_url: get_base_url(), extra_body_html: extra_body_html.unwrap_or_default(), extra_head_html: extra_head_html.unwrap_or_default(), groups, page_title: "Tildes Statistics".to_string(), today: today(), user_count: user_count.unwrap_or(1), } } /// Render the template and write it to file. pub async fn render_to_file(&self, parent: &PathBuf) -> Result<()> { write(parent.join("index.html"), self.render()?).await?; Ok(()) } } /// The template for group-specific pages. #[derive(Template)] #[template(path = "group.html")] pub struct GroupTemplate { /// The base URL for links to the Tildes instance. pub base_url: String, /// Extra HTML to insert in the body. pub extra_body_html: String, /// Extra HTML to insert in the head. pub extra_head_html: String, /// The description for this group. pub group_description: Option<String>, /// The name for this group. pub group_name: String, /// The string for the `<title>` element. pub page_title: String, /// The date of today's snapshot. pub today: NaiveDate, } impl GroupTemplate { /// Create a new [`GroupTemplate`]. pub async fn new( group_description: Option<String>, group_name: &str, ) -> Self { let extra_body_html = read_to_string("extra-body.html").await; let extra_head_html = read_to_string("extra-head.html").await; Self { base_url: get_base_url(), extra_body_html: extra_body_html.unwrap_or_default(), extra_head_html: extra_head_html.unwrap_or_default(), group_description, group_name: group_name.to_string(), page_title: "Tildes Statistics".to_string(), today: today(), } } /// Render the template and write it to file. pub async fn render_to_file(&self, parent: &PathBuf) -> Result<()> { let output_dir = parent.join(&self.group_name); create_dir_all(&output_dir).await?; write(output_dir.join("index.html"), self.render()?).await?; Ok(()) } } mod filters { pub fn percentage(a: &i64, b: &i64) -> askama::Result<String> { let percentage = (*a as f64 / *b as f64) * 100_f64; Ok(format!("{:.2}%", percentage)) } }