use std::collections::HashSet; use chrono::{DateTime, Utc}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TaskPriority { High, Medium, Low, None, } impl Into for TaskPriority { fn into(self) -> usize { match self { TaskPriority::High => 0, TaskPriority::Medium => 1, TaskPriority::Low => 2, TaskPriority::None => 3, } } } impl Default for TaskPriority { fn default() -> Self { TaskPriority::None } } impl std::fmt::Display for TaskPriority { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TaskPriority::High => write!(f, "High"), TaskPriority::Medium => write!(f, "Medium"), TaskPriority::Low => write!(f, "Low"), TaskPriority::None => write!(f, "None"), } } } impl Into for TaskPriority { fn into(self) -> String { match self { TaskPriority::High => "High".to_string(), TaskPriority::Medium => "Medium".to_string(), TaskPriority::Low => "Low".to_string(), TaskPriority::None => "None".to_string(), } } } impl From<&str> for TaskPriority { fn from(s: &str) -> Self { match s { "high" | "High" | "H" | "h" => TaskPriority::High, "medium" | "Medium" | "M" | "m" => TaskPriority::Medium, "low" | "Low" | "L" | "l" => TaskPriority::Low, _ => TaskPriority::None, } } } impl From for TaskPriority { fn from(s: String) -> Self { Self::from(s.as_str()) } } #[derive(Debug, Clone, PartialEq, Eq)] pub enum TaskStatus { Pending, Completed, Deleted, Unknown(String), Recurring, } impl Default for TaskStatus { fn default() -> Self { TaskStatus::Pending } } impl Into for TaskStatus { fn into(self) -> String { match self { TaskStatus::Pending => "Pending".to_string(), TaskStatus::Completed => "Completed".to_string(), TaskStatus::Deleted => "Deleted".to_string(), TaskStatus::Unknown(reason) => format!("Unknown({})", reason), TaskStatus::Recurring => "Recurring".to_string(), } } } impl From<&str> for TaskStatus { fn from(s: &str) -> Self { match s { "pending" | "Pending" | "P" | "p" => TaskStatus::Pending, "completed" | "Completed" | "C" | "c" => TaskStatus::Completed, "deleted" | "Deleted" | "D" | "d" => TaskStatus::Deleted, "recurring" | "Recurring" | "R" | "r" => TaskStatus::Recurring, _ => TaskStatus::Unknown(String::new()), } } } impl From for TaskStatus { fn from(s: String) -> Self { Self::from(s.as_str()) } } impl From for TaskStatus { fn from(status: taskchampion::Status) -> Self { match status { taskchampion::Status::Pending => TaskStatus::Pending, taskchampion::Status::Completed => TaskStatus::Completed, taskchampion::Status::Deleted => TaskStatus::Deleted, taskchampion::Status::Unknown(reason) => TaskStatus::Unknown(reason), taskchampion::Status::Recurring => TaskStatus::Recurring, } } } impl std::fmt::Display for TaskStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TaskStatus::Pending => write!(f, "Pending"), TaskStatus::Completed => write!(f, "Completed"), TaskStatus::Deleted => write!(f, "Deleted"), TaskStatus::Unknown(reason) => write!(f, "Unknown ({})", reason), TaskStatus::Recurring => write!(f, "Recurring"), } } } #[derive(Debug, Clone, Default)] pub struct TaskAnnotation { pub entry: DateTime, pub content: String, } impl From for TaskAnnotation { fn from(annotation: taskchampion::Annotation) -> Self { TaskAnnotation { entry: annotation.entry, content: annotation.description, } } } #[derive(Debug, Clone, Default)] pub struct Task { pub uuid: uuid::Uuid, pub id: Option, pub status: TaskStatus, pub description: String, pub project: Option, pub priority: TaskPriority, pub tags: HashSet, pub due: Option>, pub wait: Option>, pub entry: Option>, pub modified: Option>, pub annotations: Vec, pub dependencies: HashSet, pub is_active: bool, pub is_blocked: bool, pub working_id: Option, } impl Task { pub fn new( uuid: uuid::Uuid, id: Option, status: TaskStatus, description: String, project: Option, priority: TaskPriority, tags: HashSet, due: Option>, wait: Option>, entry: Option>, modified: Option>, annotations: Vec, dependencies: HashSet, is_active: bool, is_blocked: bool, working_id: Option, ) -> Self { Self { uuid, status, description, project, priority, tags, due, wait, entry, modified, annotations, dependencies, is_active, is_blocked, id, working_id, } } pub fn is_overdue(&self) -> bool { self.due.map_or(false, |due| due < Utc::now()) } pub fn is_due_today(&self) -> bool { self.due .map_or(false, |due| due.date_naive() == Utc::now().date_naive()) } } impl From for Task { fn from(task: taskchampion::Task) -> Self { Self { uuid: task.get_uuid(), id: task.get_value("ID").map(|value| value.parse().unwrap()), status: task.get_status().into(), description: task.get_description().to_string(), project: task.get_value("project").map(|v| v.to_string()), priority: task.get_priority().into(), tags: task.get_tags().map(|t| t.to_string()).collect(), due: task.get_due().map(Into::into), wait: task.get_wait().map(Into::into), entry: task.get_entry().map(Into::into), modified: task.get_modified().map(Into::into), annotations: task.get_annotations().map(Into::into).collect(), dependencies: task.get_dependencies().map(Into::into).collect(), is_active: task.is_active(), is_blocked: task.is_blocked(), working_id: None, } } } pub struct TaskUpdate { pub description: Option, pub project: Option, pub priority: Option, pub tags: Option>, pub due: Option>, pub wait: Option>, pub annotations: Option>, pub dependencies: Option>, } #[derive(Debug, Clone)] pub struct TaskOverview { pub tasks: Vec, pub projects: Vec<(String, usize)>, pub tags: Vec<(String, usize)>, pub total_tasks: usize, pub pending_tasks: usize, pub completed_tasks: usize, }