pharmacy/src/html.rs

186 lines
4.8 KiB
Rust

use serde::{Deserialize, Serialize};
use std::io::{Read, Write};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex;
use tera::{Context, Tera};
use toml::Value;
#[derive(Serialize)]
struct NavLink {
href: String,
text: String,
active: AtomicBool,
}
#[derive(Serialize, Deserialize)]
struct Config {
title: String,
description: String,
index: Page,
about: Page,
contact: Page,
products: Products,
}
#[derive(Serialize, Deserialize)]
struct Products {
label: String,
href: String,
title: String,
estrogens: Page,
anti_androgens: Page,
progestogens: Page,
}
#[derive(Serialize, Deserialize)]
struct Page {
label: String,
href: String,
title: String,
}
pub fn render_pages() {
// Read in TOML
let mut config_file = std::fs::File::open("config.toml").unwrap();
let mut contents = String::new();
config_file.read_to_string(&mut contents).unwrap();
let config: Config = toml::from_str(&contents).unwrap();
println!("{}", config.index.href);
// Use globbing
let tera = match Tera::new("templates/**/*.html") {
Ok(t) => t,
Err(e) => {
println!("Parsing error(s): {}", e);
::std::process::exit(1);
}
};
// Setup basic elements
let nav_home = NavLink {
href: config.index.href,
text: config.index.label.clone(),
active: AtomicBool::new(true),
};
let nav_about = NavLink {
href: config.about.href,
text: config.about.label.clone(),
active: AtomicBool::new(false),
};
let nav_products = NavLink {
href: config.products.href,
text: config.products.label.clone(),
active: AtomicBool::new(false),
};
let nav_contact = NavLink {
href: config.contact.href,
text: config.contact.label.clone(),
active: AtomicBool::new(false),
};
let nav_elements = vec![nav_home, nav_about, nav_products, nav_contact];
let estrogens = NavLink {
href: config.products.estrogens.href,
text: config.products.estrogens.label.clone(),
active: AtomicBool::new(false),
};
let aa = NavLink {
href: config.products.anti_androgens.href,
text: config.products.anti_androgens.label.clone(),
active: AtomicBool::new(false),
};
let progestogens = NavLink {
href: config.products.progestogens.href,
text: config.products.progestogens.label.clone(),
active: AtomicBool::new(false),
};
let product_classes = vec![estrogens, aa, progestogens];
// Render pages
let index_render = RenderObject {
url: "index.html".to_string(),
tera: tera.clone(),
subtitle: &config.index.title,
active_page: &config.index.label,
title: &config.title,
description: &config.description,
};
render_page(
// Home
index_render,
&nav_elements,
&product_classes,
);
let about_render = RenderObject {
url: "about/index.html".to_string(),
tera: tera.clone(),
subtitle: &config.about.title,
active_page: &config.about.label,
title: &config.title,
description: &config.description,
};
render_page(
// About
about_render,
&nav_elements,
&product_classes,
);
let contact_render = RenderObject {
url: "contact/index.html".to_string(),
tera: tera.clone(),
subtitle: &config.contact.title,
active_page: &config.contact.label,
title: &config.title,
description: &config.description,
};
render_page(
// About
contact_render,
&nav_elements,
&product_classes,
);
}
struct RenderObject<'a> {
url: String,
tera: Tera,
subtitle: &'a str,
active_page: &'a str,
title: &'a str,
description: &'a str,
}
fn render_page(data: RenderObject, nav_elements: &[NavLink], product_classes: &[NavLink]) {
let mut output_file =
std::fs::File::create(format!("static/{}", data.url)).expect("create failed");
for i in nav_elements {
if i.text == data.active_page {
i.active.store(true, Ordering::Relaxed);
} else {
i.active.store(false, Ordering::Relaxed);
}
}
let mut context = Context::new();
context.insert("title", data.title);
context.insert("description", data.description);
context.insert("subtitle", &data.subtitle);
for i in nav_elements {
context.insert(&i.text.to_ascii_lowercase(), &i);
}
context.insert("product_classes", &product_classes);
if data.active_page == "Contact" {
context.insert("is_contact", &true);
} else {
context.insert("is_contact", &false);
}
output_file
.write_all(data.tera.render(&data.url, &context).unwrap().as_bytes())
.expect("write failed");
}