From 91f355c17e8c70ef20d7130bc581036b02b74e35 Mon Sep 17 00:00:00 2001 From: Yoshihiro OKUMURA Date: Wed, 25 Mar 2026 12:51:45 +0900 Subject: [PATCH] feat: enhance configuration and templates for HTML output --- .vscode/extensions.json | 13 +++--- README.md | 9 ++-- crates/core/src/config.rs | 57 ++++++++++++++++++++++-- etc/digitemp-rrdgraph.sample.json | 2 + src/commands/update.rs | 18 +++++--- templates/index.html.tera | 74 +++++++++++++++++++++++++++++++ templates/index.tera | 72 ------------------------------ 7 files changed, 155 insertions(+), 90 deletions(-) create mode 100644 templates/index.html.tera delete mode 100644 templates/index.tera diff --git a/.vscode/extensions.json b/.vscode/extensions.json index c96124c..c4703f7 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,8 @@ { - "recommendations": [ - "1yib.rust-bundle", - "streetsidesoftware.code-spell-checker", - "esbenp.prettier-vscode" - ] -} \ No newline at end of file + "recommendations": [ + "1yib.rust-bundle", + "streetsidesoftware.code-spell-checker", + "esbenp.prettier-vscode", + "karunamurti.tera" + ] +} diff --git a/README.md b/README.md index e02e6db..8a3a9f7 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,14 @@ Pass `--verbose` if you want the CLI to print the selected configuration file pa Configure at least these values: - `digitemp` and `digitemp_config` -- `database_dir` and `images_dir` -- `templates_dir` +- `database_dir`, `html_dir`, and `images_dir` +- `templates_dir` and `html_template` - `room_name` - SMTP server settings - mail recipients, subjects, and alert thresholds `room_name` is required. It is used in mail templates, graph titles, and the generated top page. -The `update` command also regenerates `html/index.html` from the template so the page title and heading stay aligned with `room_name`. +The `update` command renders `html_template` and writes it under `html_dir` using the same relative path with the `.tera` suffix removed. For example, `index.html.tera` becomes `html/index.html`. SMTP settings support these combinations: @@ -140,7 +140,8 @@ See `etc/crontab.sample` for a sample schedule. ## Templates -Mail templates are stored in `templates/` and rendered with [Tera](https://tera.netlify.app/). +Templates are stored in `templates/` and rendered with [Tera](https://tera.netlify.app/). +The top page uses `html_template`, while the mail bodies use `mail_info_template` and `mail_alert_template`. ## Development Notes diff --git a/crates/core/src/config.rs b/crates/core/src/config.rs index 080d604..9edd683 100644 --- a/crates/core/src/config.rs +++ b/crates/core/src/config.rs @@ -15,14 +15,21 @@ fn default_mail_smtp_auth() -> bool { true } +fn default_html_template() -> String { + "index.html.tera".to_string() +} + #[derive(Debug, Deserialize)] pub struct Config { pub url: String, pub digitemp: String, pub digitemp_config: String, pub database_dir: String, + pub html_dir: String, pub images_dir: String, pub templates_dir: String, + #[serde(default = "default_html_template")] + pub html_template: String, pub room_name: String, pub mail_alert_upper: f64, pub mail_alert_lower: f64, @@ -57,6 +64,46 @@ mod tests { "digitemp": "/bin/digitemp_DS9097U", "digitemp_config": "etc/digitemp.conf", "database_dir": "db", + "html_dir": "html", + "images_dir": "html/images", + "templates_dir": "templates", + "html_template": "index.html.tera", + "room_name": "S108", + "mail_alert_upper": 30, + "mail_alert_lower": 17, + "mail_from": "from@example.com", + "mail_from_name": "Temperature Monitor", + "mail_info_to": "info@example.com", + "mail_info_subject": "Info", + "mail_info_template": "mail_info.tera", + "mail_alert_to": "alert@example.com", + "mail_alert_subject": "Alert", + "mail_alert_template": "mail_alert.tera", + "mail_smtp_server": "localhost", + "mail_smtp_port": 587, + "mail_smtp_username": "user@example.com", + "mail_smtp_password": "password" + }"#; + + let config: Config = serde_json::from_str(json).unwrap(); + + assert!(matches!( + config.mail_smtp_security, + MailSmtpSecurity::Starttls + )); + assert!(config.mail_smtp_auth); + assert_eq!(config.html_template, "index.html.tera"); + assert_eq!(config.room_name().unwrap(), "S108"); + } + + #[test] + fn config_defaults_html_template() { + let json = r#"{ + "url": "https://example.com/temperature/", + "digitemp": "/bin/digitemp_DS9097U", + "digitemp_config": "etc/digitemp.conf", + "database_dir": "db", + "html_dir": "html", "images_dir": "html/images", "templates_dir": "templates", "room_name": "S108", @@ -78,9 +125,7 @@ mod tests { let config: Config = serde_json::from_str(json).unwrap(); - assert!(matches!(config.mail_smtp_security, MailSmtpSecurity::Starttls)); - assert!(config.mail_smtp_auth); - assert_eq!(config.room_name().unwrap(), "S108"); + assert_eq!(config.html_template, "index.html.tera"); } #[test] @@ -90,8 +135,10 @@ mod tests { "digitemp": "/bin/digitemp_DS9097U", "digitemp_config": "etc/digitemp.conf", "database_dir": "db", + "html_dir": "html", "images_dir": "html/images", "templates_dir": "templates", + "html_template": "index.html.tera", "room_name": "S108", "mail_alert_upper": 30, "mail_alert_lower": 17, @@ -125,8 +172,10 @@ mod tests { "digitemp": "/bin/digitemp_DS9097U", "digitemp_config": "etc/digitemp.conf", "database_dir": "db", + "html_dir": "html", "images_dir": "html/images", "templates_dir": "templates", + "html_template": "index.html.tera", "room_name": " ", "mail_alert_upper": 30, "mail_alert_lower": 17, @@ -156,8 +205,10 @@ mod tests { "digitemp": "/bin/digitemp_DS9097U", "digitemp_config": "etc/digitemp.conf", "database_dir": "db", + "html_dir": "html", "images_dir": "html/images", "templates_dir": "templates", + "html_template": "index.html.tera", "mail_alert_upper": 30, "mail_alert_lower": 17, "mail_from": "from@example.com", diff --git a/etc/digitemp-rrdgraph.sample.json b/etc/digitemp-rrdgraph.sample.json index 484718c..ce5edd5 100644 --- a/etc/digitemp-rrdgraph.sample.json +++ b/etc/digitemp-rrdgraph.sample.json @@ -3,8 +3,10 @@ "digitemp": "/bin/digitemp_DS9097U", "digitemp_config": "/opt/digitemp-rrdgraph/etc/digitemp.conf", "database_dir": "/opt/digitemp-rrdgraph/db", + "html_dir": "/opt/digitemp-rrdgraph/html", "images_dir": "/opt/digitemp-rrdgraph/html/images", "templates_dir": "/opt/digitemp-rrdgraph/templates", + "html_template": "index.html.tera", "room_name": "C407", "mail_alert_upper": 30, "mail_alert_lower": 17, diff --git a/src/commands/update.rs b/src/commands/update.rs index 5f4671a..d93c49c 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs @@ -7,6 +7,14 @@ use std::fs; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; +fn output_path_for_template(config: &Config) -> Result> { + let output_name = config + .html_template + .strip_suffix(".tera") + .ok_or("html_template must end with .tera")?; + Ok(Path::new(&config.html_dir).join(output_name)) +} + pub fn run(config: &Config) -> Result<(), Box> { let room_name = config.room_name()?; let digitemp = DigiTemp::new(config.digitemp.clone(), config.digitemp_config.clone())?; @@ -41,11 +49,11 @@ pub fn run(config: &Config) -> Result<(), Box> { let engine = TemplateEngine::new(&config.templates_dir)?; let mut ctx = TemplateContext::new(); ctx.insert("room_name", &room_name); - let html = engine.render("index.tera", &ctx)?; - let index_path = Path::new(&config.images_dir) - .parent() - .unwrap_or_else(|| Path::new("html")) - .join("index.html"); + let html = engine.render(&config.html_template, &ctx)?; + let index_path = output_path_for_template(config)?; + if let Some(parent) = index_path.parent() { + fs::create_dir_all(parent)?; + } fs::write(index_path, html)?; Ok(()) diff --git a/templates/index.html.tera b/templates/index.html.tera new file mode 100644 index 0000000..bbcc512 --- /dev/null +++ b/templates/index.html.tera @@ -0,0 +1,74 @@ + + + + + + Temperature Monitor - {{ room_name }} + + + + + + + + +

Temperature Monitor - {{ room_name }}

+ +
+
+
+ Hour: + 1 ... + 3 ... + 6 ... + 12 +
+
Hourly Graph
+
+
+
+ Day: + 1 ... + 3 +
+
Daily Graph
+
+
+
+ Week: + 1 ... + 2 +
+
Weekly Graph
+
+
+
+ Month: + 1 ... + 3 ... + 6 +
+
Monthly Graph
+
+
+
+ Year: + 1 ... + 3 ... + 5 ... + 10 +
+
Yearly Graph
+
+
+ + + + \ No newline at end of file diff --git a/templates/index.tera b/templates/index.tera deleted file mode 100644 index 3292dc2..0000000 --- a/templates/index.tera +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Temperature Monitor - {{ room_name }} - - - - - - - - -

Temperature Monitor - {{ room_name }}

- -
-
-
- Hour: - 1 ... - 3 ... - 6 ... - 12 -
-
Hourly Graph
-
-
-
- Day: - 1 ... - 3 -
-
Daily Graph
-
-
-
- Week: - 1 ... - 2 -
-
Weekly Graph
-
-
-
- Month: - 1 ... - 3 ... - 6 -
-
Monthly Graph
-
-
-
- Year: - 1 ... - 3 ... - 5 ... - 10 -
-
Yearly Graph
-
-
- - - \ No newline at end of file