Skip to main content

things3_cloud/wire/
checklist.rs

1use crate::ids::ThingsId;
2use crate::wire::task::TaskStatus;
3use crate::wire::{deserialize_default_on_null, deserialize_vec_or_single};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::BTreeMap;
7
8fn is_false(v: &bool) -> bool {
9    !*v
10}
11
12/// Checklist item wire properties.
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
14pub struct ChecklistItemProps {
15    /// `tt`: checklist item title.
16    #[serde(rename = "tt", default)]
17    pub title: String,
18
19    /// `ss`: checklist item status.
20    #[serde(rename = "ss", default)]
21    pub status: TaskStatus,
22
23    /// `sp`: completion/cancellation timestamp.
24    #[serde(rename = "sp", default, skip_serializing_if = "Option::is_none")]
25    pub stop_date: Option<f64>,
26
27    /// `ts`: parent task IDs (normally a single task UUID).
28    #[serde(rename = "ts", default, deserialize_with = "deserialize_vec_or_single")]
29    pub task_ids: Vec<ThingsId>,
30
31    /// `ix`: sort index within checklist.
32    #[serde(rename = "ix", default)]
33    pub sort_index: i32,
34
35    /// `cd`: creation timestamp.
36    #[serde(rename = "cd", default, skip_serializing_if = "Option::is_none")]
37    pub creation_date: Option<f64>,
38
39    /// `md`: modification timestamp.
40    #[serde(rename = "md", default, skip_serializing_if = "Option::is_none")]
41    pub modification_date: Option<f64>,
42
43    /// `lt`: leaves tombstone on delete.
44    #[serde(
45        rename = "lt",
46        default,
47        deserialize_with = "deserialize_default_on_null",
48        skip_serializing_if = "is_false"
49    )]
50    pub leaves_tombstone: bool,
51
52    /// `xx`: conflict override metadata.
53    #[serde(rename = "xx", default, skip_serializing_if = "Option::is_none")]
54    pub conflict_overrides: Option<Value>,
55}
56
57/// Sparse patch fields for ChecklistItem `t=1` updates.
58#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
59pub struct ChecklistItemPatch {
60    /// `tt`: title.
61    #[serde(rename = "tt", skip_serializing_if = "Option::is_none")]
62    pub title: Option<String>,
63
64    /// `ss`: status.
65    #[serde(rename = "ss", skip_serializing_if = "Option::is_none")]
66    pub status: Option<TaskStatus>,
67
68    /// `ts`: parent task IDs.
69    #[serde(rename = "ts", skip_serializing_if = "Option::is_none")]
70    pub task_ids: Option<Vec<ThingsId>>,
71
72    /// `ix`: sort index.
73    #[serde(rename = "ix", skip_serializing_if = "Option::is_none")]
74    pub sort_index: Option<i32>,
75
76    /// `cd`: creation timestamp.
77    #[serde(rename = "cd", skip_serializing_if = "Option::is_none")]
78    pub creation_date: Option<f64>,
79
80    /// `md`: modification timestamp.
81    #[serde(rename = "md", skip_serializing_if = "Option::is_none")]
82    pub modification_date: Option<f64>,
83}
84
85impl ChecklistItemPatch {
86    pub fn is_empty(&self) -> bool {
87        self.title.is_none()
88            && self.status.is_none()
89            && self.task_ids.is_none()
90            && self.sort_index.is_none()
91            && self.creation_date.is_none()
92            && self.modification_date.is_none()
93    }
94
95    pub fn into_properties(self) -> BTreeMap<String, Value> {
96        match serde_json::to_value(self) {
97            Ok(Value::Object(map)) => map.into_iter().collect(),
98            _ => BTreeMap::new(),
99        }
100    }
101}