1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ClickUpUser {
14 pub id: u64,
15 pub username: String,
16 #[serde(default)]
17 pub email: Option<String>,
18 #[serde(default, rename = "profilePicture")]
19 pub profile_picture: Option<String>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct ClickUpTask {
28 pub id: String,
29 #[serde(default)]
30 pub custom_id: Option<String>,
31 pub name: String,
32 #[serde(default)]
33 pub description: Option<String>,
34 #[serde(default)]
35 pub text_content: Option<String>,
36 pub status: ClickUpStatus,
37 #[serde(default)]
38 pub priority: Option<ClickUpPriority>,
39 #[serde(default)]
40 pub tags: Vec<ClickUpTag>,
41 #[serde(default)]
42 pub assignees: Vec<ClickUpUser>,
43 #[serde(default)]
44 pub creator: Option<ClickUpUser>,
45 pub url: String,
46 #[serde(default)]
47 pub date_created: Option<String>,
48 #[serde(default)]
49 pub date_updated: Option<String>,
50 #[serde(default)]
51 pub parent: Option<String>,
52 #[serde(default)]
53 pub subtasks: Option<Vec<ClickUpTask>>,
54 #[serde(default)]
57 pub dependencies: Option<Vec<serde_json::Value>>,
58 #[serde(default)]
60 pub linked_tasks: Option<Vec<ClickUpLinkedTask>>,
61 #[serde(default)]
66 pub attachments: Vec<ClickUpAttachment>,
67 #[serde(default)]
73 pub custom_fields: Vec<ClickUpCustomField>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct ClickUpCustomField {
79 pub id: String,
80 #[serde(default)]
81 pub name: Option<String>,
82 #[serde(default, rename = "type")]
85 pub field_type: Option<String>,
86 #[serde(default)]
89 pub value: Option<serde_json::Value>,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct ClickUpAttachment {
95 pub id: String,
96 #[serde(default)]
97 pub title: Option<String>,
98 #[serde(default)]
100 pub url: Option<String>,
101 #[serde(default)]
103 pub size: Option<serde_json::Value>,
104 #[serde(default)]
106 pub extension: Option<String>,
107 #[serde(default)]
108 pub mimetype: Option<String>,
109 #[serde(default)]
111 pub date: Option<String>,
112 #[serde(default)]
114 pub user: Option<ClickUpUser>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct ClickUpStatus {
120 pub status: String,
121 #[serde(default, rename = "type")]
122 pub status_type: Option<String>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct ClickUpPriority {
128 pub id: String,
129 pub priority: String,
130 #[serde(default)]
131 pub color: Option<String>,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct ClickUpTag {
136 pub name: String,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct ClickUpLinkedTask {
142 pub task_id: String,
143 pub link_id: String,
144 #[serde(default)]
146 pub link_type: Option<String>,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct ClickUpTaskList {
156 pub tasks: Vec<ClickUpTask>,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct ClickUpComment {
165 pub id: String,
166 pub comment_text: String,
167 #[serde(default)]
168 pub user: Option<ClickUpUser>,
169 #[serde(default)]
170 pub date: Option<String>,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct ClickUpCommentList {
176 pub comments: Vec<ClickUpComment>,
177}
178
179#[derive(Debug, Clone, Deserialize)]
185pub struct ClickUpListStatus {
186 pub status: String,
187 #[serde(default, rename = "type")]
188 pub status_type: Option<String>,
189 #[serde(default)]
190 pub color: Option<String>,
191 #[serde(default)]
192 pub orderindex: Option<u32>,
193}
194
195#[derive(Debug, Clone, Deserialize)]
197pub struct ClickUpListInfo {
198 pub statuses: Vec<ClickUpListStatus>,
199}
200
201#[derive(Debug, Clone, Deserialize)]
203pub struct ClickUpDependencyResponse {
204 #[serde(default)]
205 pub dependency: Option<serde_json::Value>,
206}
207
208#[derive(Debug, Clone, Deserialize)]
210pub struct ClickUpLinkResponse {
211 #[serde(default)]
212 pub link: Option<serde_json::Value>,
213}
214
215#[derive(Debug, Clone, Serialize)]
220pub struct CreateTaskRequest {
221 pub name: String,
222 #[serde(skip_serializing_if = "Option::is_none")]
223 pub description: Option<String>,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 pub markdown_content: Option<String>,
226 #[serde(skip_serializing_if = "Option::is_none")]
227 pub parent: Option<String>,
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub status: Option<String>,
230 #[serde(skip_serializing_if = "Option::is_none")]
231 pub priority: Option<u8>,
232 #[serde(skip_serializing_if = "Option::is_none")]
233 pub tags: Option<Vec<String>>,
234 #[serde(skip_serializing_if = "Option::is_none")]
235 pub assignees: Option<Vec<u64>>,
236}
237
238#[derive(Debug, Clone, Serialize, Default)]
239pub struct UpdateTaskRequest {
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub name: Option<String>,
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub description: Option<String>,
244 #[serde(skip_serializing_if = "Option::is_none")]
245 pub markdown_content: Option<String>,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub status: Option<String>,
248 #[serde(skip_serializing_if = "Option::is_none")]
249 pub priority: Option<u8>,
250 #[serde(skip_serializing_if = "Option::is_none")]
251 pub parent: Option<String>,
252 #[serde(skip_serializing_if = "Option::is_none")]
253 pub tags: Option<Vec<String>>,
254}
255
256#[derive(Debug, Clone, Serialize)]
257pub struct CreateCommentRequest {
258 pub comment_text: String,
259}
260
261#[derive(Debug, Clone, Deserialize)]
264pub struct CreateCommentResponse {
265 #[serde(deserialize_with = "value_to_string")]
266 pub id: String,
267 #[serde(default, deserialize_with = "option_value_to_string")]
268 pub date: Option<String>,
269}
270
271fn value_to_string<'de, D>(deserializer: D) -> std::result::Result<String, D::Error>
273where
274 D: serde::Deserializer<'de>,
275{
276 let value = serde_json::Value::deserialize(deserializer)?;
277 match value {
278 serde_json::Value::String(s) => Ok(s),
279 serde_json::Value::Number(n) => Ok(n.to_string()),
280 other => Ok(other.to_string()),
281 }
282}
283
284fn option_value_to_string<'de, D>(deserializer: D) -> std::result::Result<Option<String>, D::Error>
286where
287 D: serde::Deserializer<'de>,
288{
289 let value = Option::<serde_json::Value>::deserialize(deserializer)?;
290 Ok(value.map(|v| match v {
291 serde_json::Value::String(s) => s,
292 serde_json::Value::Number(n) => n.to_string(),
293 other => other.to_string(),
294 }))
295}