1use anyhow::Error;
2use fake::Dummy;
3use fake::Fake;
4use serde::Deserialize;
5use serde::Serialize;
6use serde_json::Value;
7
8use crate::types::ResultAnyError;
9
10#[derive(Serialize, Deserialize, Debug)]
11pub struct TaskFamily {
12 pub parent_task: Task,
13 pub children: Vec<TaskFamily>,
14}
15
16impl TaskFamily {
17 pub fn json_string(task_families: &[TaskFamily]) -> ResultAnyError<String> {
18 return serde_json::to_string(task_families).map_err(Error::new);
19 }
20}
21
22#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
23pub struct Task {
24 pub id: String,
25 pub task_type: String,
26 pub phid: String,
27 pub name: String,
28 pub description: String,
29 pub author_phid: String,
30 pub assigned_phid: Option<String>,
31 pub status: String,
32 pub priority: String,
33 pub point: Option<u64>,
34 pub project_phids: Vec<String>,
35 pub board: Option<Board>,
36 pub created_at: u64,
37 pub updated_at: u64,
38}
39
40impl Task {
41 pub fn from_json(v: &Value) -> Task {
42 let project_phids: &Vec<Value> = match &v["attachments"]["projects"]["projectPHIDs"] {
43 Value::Array(arr) => arr,
44 _ => panic!(
45 "Project phids is not an array {:?}",
46 v["attachments"]["projects"]["projectPHIDs"]
47 ),
48 };
49
50 let project_phids: Vec<String> = project_phids.iter().map(json_to_string).collect();
51
52 let board: Option<&Value> =
53 Task::guess_board_from_projects(&v["attachments"]["columns"]["boards"], &project_phids);
54 let fields: &Value = &v["fields"];
55
56 let task = Task {
57 id: format!("{}", v["id"].as_u64().unwrap()),
58 task_type: json_to_string(&v["type"]),
59 phid: json_to_string(&v["phid"]),
60 name: json_to_string(&fields["name"]),
61 description: json_to_string(&fields["description"]["raw"]),
62 author_phid: json_to_string(&fields["authorPHID"]),
63 assigned_phid: fields["ownerPHID"].as_str().map(Into::into),
64 status: json_to_string(&fields["status"]["value"]),
65 priority: json_to_string(&fields["priority"]["name"]),
66 point: fields["points"].as_u64(),
67 project_phids,
68 board: board.map(|board: &Value| {
69 return Board {
70 id: board["id"].as_u64().unwrap(),
71 phid: board["phid"].as_str().unwrap().into(),
72 name: board["name"].as_str().unwrap().into(),
73 };
74 }),
75 created_at: fields["dateCreated"].as_u64().unwrap(),
76 updated_at: fields["dateModified"].as_u64().unwrap(),
77 };
78
79 return task;
80 }
81
82 pub fn guess_board_from_projects<'a>(
83 boards: &'a Value,
84 project_phids: &[String],
85 ) -> Option<&'a Value> {
86 return project_phids
87 .iter()
88 .find(|phid| {
89 return boards[phid] != Value::Null;
90 })
91 .map(|phid| &boards[&phid]["columns"][0]);
92 }
93}
94
95fn json_to_string(v: &Value) -> String {
96 return v.as_str().unwrap().into();
97}
98
99#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
100pub struct Board {
101 pub id: u64,
102 pub phid: String,
103 pub name: String,
104}
105
106#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
107pub struct Watchlist {
108 pub id: Option<String>,
109 pub name: String,
110 pub tasks: Vec<Task>,
111}
112
113#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
114pub struct User {
115 pub id: String,
116 pub phid: String,
117 pub username: String,
118 pub name: String,
119 pub created_at: u64,
120 pub updated_at: u64,
121}
122
123impl User {
124 pub fn from_json(v: &Value) -> User {
125 let fields: &Value = &v["fields"];
126
127 return User {
128 id: format!("{}", v["id"].as_u64().unwrap()),
129 phid: json_to_string(&v["phid"]),
130 username: json_to_string(&fields["username"]),
131 name: json_to_string(&fields["realName"]),
132 created_at: fields["dateCreated"].as_u64().unwrap(),
133 updated_at: fields["dateModified"].as_u64().unwrap(),
134 };
135 }
136}