use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub id: String,
#[serde(default)]
pub login: Option<String>,
#[serde(default)]
pub display: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DictEntry {
pub key: String,
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub order: Option<i64>,
#[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
pub category: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Person {
pub login: String,
pub uid: String,
pub display: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
pub dismissed: bool,
pub external: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum LinkKind {
Blocks,
IsBlockedBy,
Parent,
Subtask,
Duplicates,
IsDuplicatedBy,
Depends,
IsDependentBy,
Relates,
Epic,
HasEpic,
Other,
}
impl LinkKind {
#[must_use]
pub fn label(self) -> &'static str {
match self {
Self::Blocks => "blocks",
Self::IsBlockedBy => "is blocked by",
Self::Parent => "parent",
Self::Subtask => "subtask",
Self::Duplicates => "duplicates",
Self::IsDuplicatedBy => "is duplicated by",
Self::Depends => "depends on",
Self::IsDependentBy => "is depended on by",
Self::Relates => "relates",
Self::Epic => "epic",
Self::HasEpic => "has epic",
Self::Other => "related to",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Link {
pub id: String,
pub kind: LinkKind,
#[serde(default)]
pub relation: Option<String>,
pub key: String,
#[serde(default)]
pub summary: Option<String>,
#[serde(default)]
pub status: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoteLink {
pub id: String,
#[serde(default)]
pub relation: Option<String>,
#[serde(default)]
pub application: Option<String>,
#[serde(default)]
pub key: Option<String>,
#[serde(default)]
pub title: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Issue {
pub key: String,
pub summary: String,
#[serde(default)]
pub status: Option<String>,
#[serde(default)]
pub status_key: Option<String>,
#[serde(default)]
pub issue_type: Option<String>,
#[serde(default)]
pub priority: Option<String>,
#[serde(default)]
pub priority_key: Option<String>,
#[serde(default)]
pub queue: Option<String>,
#[serde(default)]
pub assignee: Option<User>,
#[serde(default)]
pub author: Option<User>,
#[serde(default)]
pub created_at: Option<jiff::Timestamp>,
#[serde(default)]
pub updated_at: Option<jiff::Timestamp>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub links: Vec<Link>,
#[serde(default)]
pub comment_count: Option<u32>,
#[serde(default, flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Page<T> {
pub items: Vec<T>,
pub page: u32,
pub per_page: u32,
pub total: Option<u64>,
}
impl<T> Page<T> {
#[must_use]
pub fn has_more(&self) -> bool {
match self.total {
Some(total) => u64::from(self.page) * u64::from(self.per_page) < total,
None => u32::try_from(self.items.len()).is_ok_and(|len| len == self.per_page),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Comment {
pub id: String,
pub text: String,
#[serde(default)]
pub author: Option<User>,
#[serde(default)]
pub created_at: Option<jiff::Timestamp>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct Worklog {
pub id: String,
pub duration: String,
#[serde(default)]
pub author: Option<User>,
#[serde(default)]
pub start: Option<jiff::Timestamp>,
#[serde(default)]
pub comment: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub issue: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct Change {
pub id: String,
#[serde(default)]
pub at: Option<jiff::Timestamp>,
#[serde(default)]
pub by: Option<User>,
pub kind: String,
pub fields: Vec<FieldChange>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct FieldChange {
pub field: String,
#[serde(default)]
pub from: Option<String>,
#[serde(default)]
pub to: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct ChecklistItem {
pub id: String,
pub text: String,
pub checked: bool,
#[serde(default)]
pub assignee: Option<User>,
#[serde(default)]
pub deadline: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entity {
pub id: String,
pub short_id: Option<i64>,
pub entity_type: Option<String>,
pub summary: String,
#[serde(default)]
pub status: Option<String>,
#[serde(default)]
pub lead: Option<User>,
#[serde(default)]
pub start: Option<String>,
#[serde(default)]
pub end: Option<String>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub parent: Option<String>,
#[serde(default)]
pub version: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Attachment {
pub id: String,
pub name: String,
pub size: Option<u64>,
pub mimetype: Option<String>,
#[serde(default)]
pub author: Option<User>,
#[serde(default)]
pub created_at: Option<jiff::Timestamp>,
pub content: Option<String>,
}