1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use fake::Dummy;
use fake::Fake;
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value;

use crate::types::ResultDynError;

#[derive(Serialize, Deserialize, Debug)]
pub struct TaskFamily {
  pub parent_task: Task,
  pub children: Vec<TaskFamily>,
}

impl TaskFamily {
  pub fn json_string(task_families: &[TaskFamily]) -> ResultDynError<String> {
    return serde_json::to_string(task_families).map_err(failure::Error::from);
  }
}

#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
pub struct Task {
  pub id: String,
  pub task_type: String,
  pub phid: String,
  pub name: String,
  pub description: String,
  pub author_phid: String,
  pub assigned_phid: Option<String>,
  pub status: String,
  pub priority: String,
  pub point: Option<u64>,
  pub project_phids: Vec<String>,
  pub board: Option<Board>,
  pub created_at: u64,
  pub updated_at: u64,
}

impl Task {
  pub fn from_json(v: &Value) -> Task {
    let project_phids: &Vec<Value> = match &v["attachments"]["projects"]["projectPHIDs"] {
      Value::Array(arr) => arr,
      _ => panic!(
        "Project phids is not an array {:?}",
        v["attachments"]["projects"]["projectPHIDs"]
      ),
    };

    let project_phids: Vec<String> = project_phids.iter().map(json_to_string).collect();

    let board: Option<&Value> =
      Task::guess_board_from_projects(&v["attachments"]["columns"]["boards"], &project_phids);
    let fields: &Value = &v["fields"];

    let task = Task {
      id: format!("{}", v["id"].as_u64().unwrap()),
      task_type: json_to_string(&v["type"]),
      phid: json_to_string(&v["phid"]),
      name: json_to_string(&fields["name"]),
      description: json_to_string(&fields["description"]["raw"]),
      author_phid: json_to_string(&fields["authorPHID"]),
      assigned_phid: fields["ownerPHID"].as_str().map(Into::into),
      status: json_to_string(&fields["status"]["value"]),
      priority: json_to_string(&fields["priority"]["name"]),
      point: fields["points"].as_u64(),
      project_phids,
      board: board.map(|board: &Value| {
        return Board {
          id: board["id"].as_u64().unwrap(),
          phid: board["phid"].as_str().unwrap().into(),
          name: board["name"].as_str().unwrap().into(),
        };
      }),
      created_at: fields["dateCreated"].as_u64().unwrap(),
      updated_at: fields["dateModified"].as_u64().unwrap(),
    };

    return task;
  }

  pub fn guess_board_from_projects<'a>(
    boards: &'a Value,
    project_phids: &[String],
  ) -> Option<&'a Value> {
    return project_phids
      .iter()
      .find(|phid| {
        return boards[phid] != Value::Null;
      })
      .map(|phid| &boards[&phid]["columns"][0]);
  }
}

fn json_to_string(v: &Value) -> String {
  return v.as_str().unwrap().into();
}

#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
pub struct Board {
  pub id: u64,
  pub phid: String,
  pub name: String,
}

#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
pub struct Watchlist {
  pub id: Option<String>,
  pub name: String,
  pub tasks: Vec<Task>,
}

#[derive(Clone, Debug, Serialize, Deserialize, Dummy)]
pub struct User {
  pub id: String,
  pub phid: String,
  pub username: String,
  pub name: String,
  pub created_at: u64,
  pub updated_at: u64,
}

impl User {
  pub fn from_json(v: &Value) -> User {
    let fields: &Value = &v["fields"];

    return User {
      id: format!("{}", v["id"].as_u64().unwrap()),
      phid: json_to_string(&v["phid"]),
      username: json_to_string(&fields["username"]),
      name: json_to_string(&fields["realName"]),
      created_at: fields["dateCreated"].as_u64().unwrap(),
      updated_at: fields["dateModified"].as_u64().unwrap(),
    };
  }
}