diff --git a/crates/bds-core/src/db/queries/post.rs b/crates/bds-core/src/db/queries/post.rs index c27beb0..4fe5235 100644 --- a/crates/bds-core/src/db/queries/post.rs +++ b/crates/bds-core/src/db/queries/post.rs @@ -101,8 +101,8 @@ pub fn update_post(conn: &Connection, post: &Post) -> rusqlite::Result<()> { file_path = ?10, checksum = ?11, tags = ?12, categories = ?13, published_title = ?14, published_content = ?15, published_tags = ?16, published_categories = ?17, published_excerpt = ?18, - updated_at = ?19, published_at = ?20 - WHERE id = ?21", + created_at = ?19, updated_at = ?20, published_at = ?21 + WHERE id = ?22", params![ post.title, post.slug, @@ -122,6 +122,7 @@ pub fn update_post(conn: &Connection, post: &Post) -> rusqlite::Result<()> { post.published_tags, post.published_categories, post.published_excerpt, + post.created_at, post.updated_at, post.published_at, post.id, diff --git a/crates/bds-ui/src/app.rs b/crates/bds-ui/src/app.rs index 6efd222..9fec1f5 100644 --- a/crates/bds-ui/src/app.rs +++ b/crates/bds-ui/src/app.rs @@ -352,7 +352,7 @@ mod tests { use crate::views::script_editor::ScriptEditorState; use crate::views::settings_view::SettingsViewState; use crate::views::template_editor::TemplateEditorState; - use chrono::Datelike; + use chrono::{Datelike, TimeZone}; use bds_core::db::fts::ensure_fts_tables; use bds_core::db::queries::project::insert_project; use bds_core::db::Database; @@ -820,6 +820,56 @@ mod tests { assert_eq!(first.title, "First"); } + #[test] + fn dashboard_timeline_uses_created_month_not_updated_month() { + let (db, project, tmp) = setup(); + let created = post::create_post( + db.conn(), + tmp.path(), + &project.id, + "March Post", + Some("Body"), + vec![], + vec!["article".to_string()], + None, + Some("en"), + None, + ) + .unwrap(); + + let march_created_at = chrono::Utc + .with_ymd_and_hms(2026, 3, 15, 12, 0, 0) + .single() + .unwrap() + .timestamp_millis(); + let april_updated_at = chrono::Utc + .with_ymd_and_hms(2026, 4, 2, 12, 0, 0) + .single() + .unwrap() + .timestamp_millis(); + + let mut saved = bds_core::db::queries::post::get_post_by_id(db.conn(), &created.id).unwrap(); + saved.created_at = march_created_at; + saved.updated_at = april_updated_at; + bds_core::db::queries::post::update_post(db.conn(), &saved).unwrap(); + + let app = make_app(db, project, &tmp); + let dash = app.hydrate_dashboard_state(); + let march = dash + .timeline + .iter() + .find(|month| month.year == 2026 && month.label == "Mar") + .expect("march bucket should exist"); + let april = dash + .timeline + .iter() + .find(|month| month.year == 2026 && month.label == "Apr") + .expect("april bucket should exist"); + + assert_eq!(march.count, 1); + assert_eq!(april.count, 0); + } + #[test] fn save_project_persists_languages_and_blogmark_category() { let (db, project, tmp) = setup(); @@ -2747,7 +2797,7 @@ impl BdsApp { PostStatus::Archived => archived_count += 1, } - let (year, month, _) = bds_core::util::timestamp::year_month_day_from_unix_ms(post.updated_at); + let (year, month, _) = bds_core::util::timestamp::year_month_day_from_unix_ms(post.created_at); let year = year.parse::().unwrap_or(0); let month = month.parse::().unwrap_or(0); *monthly_counts.entry((year, month)).or_insert(0) += 1;