use std::str::FromStr; use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; use uuid::Uuid; pub trait ResponseData { type Response: Serialize; fn into_response(self) -> Self::Response; } #[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)] #[serde(rename_all = "lowercase")] pub enum IssueType { Task, Bug, Story, } impl FromStr for IssueType { type Err = String; fn from_str(s: &str) -> Result { match s.to_lowercase().as_str() { "task" => Ok(IssueType::Task), "bug" => Ok(IssueType::Bug), "story" => Ok(IssueType::Story), _ => Err(format!("Unknown type {:?}", s)), } } } impl ToString for IssueType { fn to_string(&self) -> String { match self { IssueType::Task => "Task", IssueType::Bug => "Bug", IssueType::Story => "Story", } .to_string() } } #[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)] pub enum IssueStatus { Backlog, Selected, InProgress, Done, } impl IssueStatus { pub fn to_label(&self) -> &str { match self { IssueStatus::Backlog => "Backlog", IssueStatus::Selected => "Selected for development", IssueStatus::InProgress => "In Progress", IssueStatus::Done => "Done", } } pub fn to_payload(&self) -> &str { match self { IssueStatus::Backlog => "backlog", IssueStatus::Selected => "selected", IssueStatus::InProgress => "in_progress", IssueStatus::Done => "done", } } #[deprecated] pub fn to_deprecated_payload(&self) -> &str { match self { IssueStatus::Backlog => "backlog", IssueStatus::Selected => "selected", IssueStatus::InProgress => "inprogress", IssueStatus::Done => "done", } } pub fn match_name(&self, name: &str) -> bool { self.to_payload() == name || self.to_deprecated_payload() == name } } #[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)] pub enum IssuePriority { Highest, High, Medium, Low, Lowest, } impl FromStr for IssuePriority { type Err = String; fn from_str(s: &str) -> Result { match s.to_lowercase().trim() { "5" | "highest" => Ok(IssuePriority::Highest), "4" | "high" => Ok(IssuePriority::High), "3" | "medium" => Ok(IssuePriority::Medium), "2" | "low" => Ok(IssuePriority::Low), "1" | "lowest" => Ok(IssuePriority::Lowest), _ => Err(format!("Unknown priority {}", s)), } } } impl IssuePriority { pub fn to_text_value(&self) -> &str { match self { IssuePriority::Highest => "5", IssuePriority::High => "4", IssuePriority::Medium => "3", IssuePriority::Low => "2", IssuePriority::Lowest => "1", } } pub fn to_lower_name(&self) -> &str { match self { IssuePriority::Highest => "highest", IssuePriority::High => "high", IssuePriority::Medium => "medium", IssuePriority::Low => "low", IssuePriority::Lowest => "lowest", } } pub fn to_value(&self) -> i32 { match self { IssuePriority::Highest => 5, IssuePriority::High => 4, IssuePriority::Medium => 3, IssuePriority::Low => 2, IssuePriority::Lowest => 1, } } } #[derive(Clone, Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct ErrorResponse { pub errors: Vec, } #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct FullProject { pub id: i32, pub name: String, pub url: String, pub description: String, pub category: String, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, pub issues: Vec, pub users: Vec, } #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct FullProjectResponse { pub project: FullProject, } impl ResponseData for FullProject { type Response = FullProjectResponse; fn into_response(self) -> Self::Response { FullProjectResponse { project: self } } } #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct FullIssue { pub id: i32, pub title: String, #[serde(rename = "type")] pub issue_type: String, pub status: String, pub priority: String, pub list_position: f64, pub description: Option, pub description_text: Option, pub estimate: Option, pub time_spent: Option, pub time_remaining: Option, pub reporter_id: i32, pub project_id: i32, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, pub user_ids: Vec, pub comments: Vec, } #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct FullIssueResponse { pub issue: FullIssue, } impl ResponseData for FullIssue { type Response = FullIssueResponse; fn into_response(self) -> Self::Response { FullIssueResponse { issue: self } } } #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Project { pub id: i32, pub name: String, pub url: String, pub description: String, pub category: String, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, } #[derive(Clone, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Issue { pub id: i32, pub title: String, #[serde(rename = "type")] pub issue_type: String, pub status: String, pub priority: String, pub list_position: f64, pub description: Option, pub description_text: Option, pub estimate: Option, pub time_spent: Option, pub time_remaining: Option, pub reporter_id: i32, pub project_id: i32, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, pub user_ids: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Comment { pub id: i32, pub body: String, pub user_id: i32, pub issue_id: i32, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, pub user: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct User { pub id: i32, pub name: String, pub email: String, pub avatar_url: Option, pub project_id: i32, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Token { pub id: i32, pub user_id: i32, pub access_token: Uuid, pub refresh_token: Uuid, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpdateIssuePayload { pub title: Option, #[serde(rename = "type")] pub issue_type: Option, pub status: Option, pub priority: Option, pub list_position: Option, pub description: Option>, pub description_text: Option>, pub estimate: Option>, pub time_spent: Option>, pub time_remaining: Option>, pub project_id: Option, pub users: Option>, pub user_ids: Option>, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateCommentPayload { pub user_id: Option, pub issue_id: i32, pub body: String, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpdateCommentPayload { pub body: String, } #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct CreateIssuePayload { pub title: String, #[serde(rename = "type")] pub issue_type: String, pub status: String, pub priority: String, pub description: Option, pub description_text: Option, pub estimate: Option, pub time_spent: Option, pub time_remaining: Option, pub project_id: i32, pub user_ids: Vec, } #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct UpdateProjectPayload { pub name: Option, pub url: Option, pub description: Option, pub category: Option, }