phab_lib/
dto.rs

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}