fix: wired engines that exist to UI
This commit is contained in:
86
crates/bds-core/src/engine/calendar.rs
Normal file
86
crates/bds-core/src/engine/calendar.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
//! Calendar JSON generation — counts posts by year, month, day.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
|
||||
use rusqlite::Connection;
|
||||
|
||||
use crate::db::queries::post as post_q;
|
||||
use crate::engine::EngineResult;
|
||||
use crate::model::PostStatus;
|
||||
use crate::util::{atomic_write, timestamp};
|
||||
|
||||
/// Generate `html/calendar.json` from published posts.
|
||||
///
|
||||
/// The JSON has three top-level objects: `years`, `months`, `days`,
|
||||
/// each mapping a date key to a count of posts.
|
||||
pub fn regenerate_calendar(
|
||||
conn: &Connection,
|
||||
data_dir: &Path,
|
||||
project_id: &str,
|
||||
) -> EngineResult<()> {
|
||||
let posts = post_q::list_posts_by_project(conn, project_id)?;
|
||||
|
||||
let mut years: BTreeMap<String, u32> = BTreeMap::new();
|
||||
let mut months: BTreeMap<String, u32> = BTreeMap::new();
|
||||
let mut days: BTreeMap<String, u32> = BTreeMap::new();
|
||||
|
||||
for post in &posts {
|
||||
if post.status != PostStatus::Published {
|
||||
continue;
|
||||
}
|
||||
let ts = post.created_at;
|
||||
let (y, m, d) = timestamp::year_month_day_from_unix_ms(ts);
|
||||
|
||||
let year_key = y.clone();
|
||||
let month_key = format!("{y}-{m}");
|
||||
let day_key = format!("{y}-{m}-{d}");
|
||||
|
||||
*years.entry(year_key).or_insert(0) += 1;
|
||||
*months.entry(month_key).or_insert(0) += 1;
|
||||
*days.entry(day_key).or_insert(0) += 1;
|
||||
}
|
||||
|
||||
let calendar = serde_json::json!({
|
||||
"years": years,
|
||||
"months": months,
|
||||
"days": days,
|
||||
});
|
||||
|
||||
let html_dir = data_dir.join("html");
|
||||
std::fs::create_dir_all(&html_dir)?;
|
||||
|
||||
let json_str = serde_json::to_string_pretty(&calendar)?;
|
||||
|
||||
atomic_write::atomic_write(&html_dir.join("calendar.json"), json_str.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::db::Database;
|
||||
use crate::engine;
|
||||
|
||||
#[test]
|
||||
fn calendar_empty_project() {
|
||||
let db = Database::open_in_memory().unwrap();
|
||||
let _ = db.migrate();
|
||||
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let p = engine::project::create_project(
|
||||
db.conn(), "Test", Some(tmp.path().to_str().unwrap()),
|
||||
).unwrap();
|
||||
|
||||
regenerate_calendar(db.conn(), tmp.path(), &p.id).unwrap();
|
||||
|
||||
let cal_path = tmp.path().join("html").join("calendar.json");
|
||||
assert!(cal_path.exists());
|
||||
|
||||
let data: serde_json::Value = serde_json::from_str(
|
||||
&std::fs::read_to_string(&cal_path).unwrap()
|
||||
).unwrap();
|
||||
assert!(data["years"].as_object().unwrap().is_empty());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user