use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use super::{CustomField, Priority, Status, User};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Task {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub list_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub folder: Option<JsonValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub space: Option<JsonValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub project: Option<JsonValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
#[serde(skip_serializing_if = "Option::is_none")]
pub priority: Option<Priority>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignees: Option<Vec<User>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub watchers: Option<Vec<User>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date_created: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date_updated: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date_closed: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_date: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub due_date: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub due_date_time: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_estimate: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_spent: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dependencies: Option<Vec<TaskDependency>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub linked_tasks: Option<Vec<LinkedTask>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom_fields: Option<Vec<CustomField>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment_count: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attachments: Option<Vec<Attachment>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub archived: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub orderindex: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub creator: Option<User>,
#[serde(skip_serializing_if = "Option::is_none")]
pub points: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub notify_all: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub markdown_description: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TaskDependency {
pub task_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub depends_on: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dependency_of: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LinkedTask {
pub task_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub link_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date_created: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Attachment {
pub id: String,
pub title: String,
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mimetype: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<User>,
}
impl Task {
pub fn new(name: impl Into<String>) -> Self {
Self {
id: None,
name: name.into(),
description: None,
list_id: None,
folder: None,
space: None,
project: None,
status: None,
priority: None,
assignees: None,
watchers: None,
date_created: None,
date_updated: None,
date_closed: None,
start_date: None,
due_date: None,
due_date_time: None,
time_estimate: None,
time_spent: None,
parent: None,
dependencies: None,
linked_tasks: None,
custom_fields: None,
tags: None,
comment_count: None,
attachments: None,
url: None,
archived: None,
orderindex: None,
creator: None,
points: None,
notify_all: None,
markdown_description: None,
}
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
pub fn with_list_id(mut self, list_id: impl Into<String>) -> Self {
self.list_id = Some(list_id.into());
self
}
pub fn with_priority(mut self, priority: Priority) -> Self {
self.priority = Some(priority);
self
}
pub fn with_status(mut self, status: Status) -> Self {
self.status = Some(status);
self
}
pub fn with_assignees(mut self, assignees: Vec<User>) -> Self {
self.assignees = Some(assignees);
self
}
pub fn with_tags(mut self, tags: Vec<String>) -> Self {
self.tags = Some(tags);
self
}
pub fn with_custom_fields(mut self, custom_fields: Vec<CustomField>) -> Self {
self.custom_fields = Some(custom_fields);
self
}
pub fn with_due_date(mut self, timestamp_ms: i64) -> Self {
self.due_date = Some(timestamp_ms);
self
}
pub fn with_parent(mut self, parent_id: impl Into<String>) -> Self {
self.parent = Some(parent_id.into());
self
}
pub fn notify_all(mut self, notify: bool) -> Self {
self.notify_all = Some(notify);
self
}
}
pub struct TaskBuilder {
task: Task,
}
impl TaskBuilder {
pub fn new(name: impl Into<String>) -> Self {
Self {
task: Task::new(name),
}
}
pub fn description(mut self, description: impl Into<String>) -> Self {
self.task = self.task.with_description(description);
self
}
pub fn list_id(mut self, list_id: impl Into<String>) -> Self {
self.task = self.task.with_list_id(list_id);
self
}
pub fn priority(mut self, priority: Priority) -> Self {
self.task = self.task.with_priority(priority);
self
}
pub fn status(mut self, status: Status) -> Self {
self.task = self.task.with_status(status);
self
}
pub fn assignees(mut self, assignees: Vec<User>) -> Self {
self.task = self.task.with_assignees(assignees);
self
}
pub fn tags(mut self, tags: Vec<String>) -> Self {
self.task = self.task.with_tags(tags);
self
}
pub fn custom_fields(mut self, custom_fields: Vec<CustomField>) -> Self {
self.task = self.task.with_custom_fields(custom_fields);
self
}
pub fn due_date(mut self, timestamp_ms: i64) -> Self {
self.task = self.task.with_due_date(timestamp_ms);
self
}
pub fn parent(mut self, parent_id: impl Into<String>) -> Self {
self.task = self.task.with_parent(parent_id);
self
}
pub fn notify_all(mut self, notify: bool) -> Self {
self.task = self.task.notify_all(notify);
self
}
pub fn build(self) -> Task {
self.task
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_task_new() {
let task = Task::new("Test Task");
assert_eq!(task.name, "Test Task");
assert!(task.id.is_none());
assert!(task.description.is_none());
}
#[test]
fn test_task_builder() {
let task = Task::new("Test")
.with_description("Description")
.with_list_id("123")
.with_priority(Priority::High)
.with_tags(vec!["urgent".to_string()]);
assert_eq!(task.name, "Test");
assert_eq!(task.description, Some("Description".to_string()));
assert_eq!(task.list_id, Some("123".to_string()));
assert_eq!(task.priority, Some(Priority::High));
assert_eq!(task.tags, Some(vec!["urgent".to_string()]));
}
#[test]
fn test_task_builder_pattern() {
let task = TaskBuilder::new("Builder Test")
.description("Using builder pattern")
.list_id("456")
.priority(Priority::Urgent)
.notify_all(true)
.build();
assert_eq!(task.name, "Builder Test");
assert_eq!(task.list_id, Some("456".to_string()));
assert_eq!(task.notify_all, Some(true));
}
}