Issue: add done_time field

This records the DateTime that the issue moved to the Done state (if any).
This commit is contained in:
Sebastian Kuzminsky 2025-07-15 15:37:23 -06:00
parent 3df76b89df
commit 3b33ed41f5
3 changed files with 25 additions and 0 deletions

View file

@ -23,6 +23,7 @@ pub struct Issue {
pub id: String, pub id: String,
pub author: String, pub author: String,
pub creation_time: chrono::DateTime<chrono::Local>, pub creation_time: chrono::DateTime<chrono::Local>,
pub done_time: Option<chrono::DateTime<chrono::Local>>,
pub tags: Vec<String>, pub tags: Vec<String>,
pub state: State, pub state: State,
pub dependencies: Option<Vec<IssueHandle>>, pub dependencies: Option<Vec<IssueHandle>>,
@ -43,6 +44,8 @@ pub enum IssueError {
EnvVarError(#[from] std::env::VarError), EnvVarError(#[from] std::env::VarError),
#[error(transparent)] #[error(transparent)]
CommentError(#[from] crate::comment::CommentError), CommentError(#[from] crate::comment::CommentError),
#[error(transparent)]
ChronoParseError(#[from] chrono::format::ParseError),
#[error("Failed to parse issue")] #[error("Failed to parse issue")]
IssueParseError, IssueParseError,
#[error("Failed to parse state")] #[error("Failed to parse state")]
@ -106,6 +109,7 @@ impl Issue {
let mut comments = Vec::<crate::comment::Comment>::new(); let mut comments = Vec::<crate::comment::Comment>::new();
let mut assignee: Option<String> = None; let mut assignee: Option<String> = None;
let mut tags = Vec::<String>::new(); let mut tags = Vec::<String>::new();
let mut done_time: Option<chrono::DateTime<chrono::Local>> = None;
for direntry in dir.read_dir()? { for direntry in dir.read_dir()? {
if let Ok(direntry) = direntry { if let Ok(direntry) = direntry {
@ -119,6 +123,11 @@ impl Issue {
assignee = Some(String::from( assignee = Some(String::from(
std::fs::read_to_string(direntry.path())?.trim(), std::fs::read_to_string(direntry.path())?.trim(),
)); ));
} else if file_name == "done_time" {
let raw_done_time = chrono::DateTime::<_>::parse_from_rfc3339(
std::fs::read_to_string(direntry.path())?.trim(),
)?;
done_time = Some(raw_done_time.into());
} else if file_name == "dependencies" { } else if file_name == "dependencies" {
let dep_strings = std::fs::read_to_string(direntry.path())?; let dep_strings = std::fs::read_to_string(direntry.path())?;
let deps: Vec<IssueHandle> = dep_strings let deps: Vec<IssueHandle> = dep_strings
@ -165,6 +174,7 @@ impl Issue {
id, id,
author, author,
creation_time, creation_time,
done_time,
tags, tags,
state: state, state: state,
dependencies, dependencies,
@ -221,6 +231,7 @@ impl Issue {
id: String::from(&issue_id), id: String::from(&issue_id),
author: String::from(""), author: String::from(""),
creation_time: chrono::Local::now(), creation_time: chrono::Local::now(),
done_time: None,
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: State::New, state: State::New,
dependencies: None, dependencies: None,
@ -453,6 +464,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::from([ tags: Vec::<String>::from([
String::from("tag1"), String::from("tag1"),
String::from("TAG2"), String::from("TAG2"),
@ -480,6 +492,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: State::InProgress, state: State::InProgress,
dependencies: None, dependencies: None,

View file

@ -93,6 +93,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: crate::issue::State::InProgress, state: crate::issue::State::InProgress,
dependencies: None, dependencies: None,
@ -112,6 +113,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T12:14:26-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::from([ tags: Vec::<String>::from([
String::from("tag1"), String::from("tag1"),
String::from("TAG2"), String::from("TAG2"),
@ -144,6 +146,11 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T11:59:44-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T11:59:44-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: Some(
chrono::DateTime::parse_from_rfc3339("2025-07-15T15:15:15-06:00")
.unwrap()
.with_timezone(&chrono::Local),
),
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: crate::issue::State::Done, state: crate::issue::State::Done,
dependencies: None, dependencies: None,
@ -177,6 +184,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T11:59:44-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-03T11:59:44-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: crate::issue::State::WontDo, state: crate::issue::State::WontDo,
dependencies: None, dependencies: None,
@ -205,6 +213,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: crate::issue::State::Done, state: crate::issue::State::Done,
dependencies: None, dependencies: None,
@ -224,6 +233,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: crate::issue::State::WontDo, state: crate::issue::State::WontDo,
dependencies: None, dependencies: None,
@ -244,6 +254,7 @@ mod tests {
creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00") creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-05T13:55:49-06:00")
.unwrap() .unwrap()
.with_timezone(&chrono::Local), .with_timezone(&chrono::Local),
done_time: None,
tags: Vec::<String>::new(), tags: Vec::<String>::new(),
state: crate::issue::State::WontDo, state: crate::issue::State::WontDo,
dependencies: Some(vec![ dependencies: Some(vec![

View file

@ -0,0 +1 @@
2025-07-15T15:15:15-06:00