1mod attachment_creation;
2mod consumer;
3mod creation;
4mod mutation;
5mod notes;
6
7use crate::choices::TaskSource;
8use crate::ids::TaskId;
9use crate::labels::CreatedLabel;
10use crate::metadata::TaskMetadataInput;
11use crate::types::Task;
12use crate::undo::TaskUndoSnapshot;
13
14pub struct TaskDraft {
15 pub title: String,
16 pub description: String,
17 pub project: Option<String>,
18 pub status: String,
19 pub priority: String,
20 pub source: TaskSource,
21 pub labels: Vec<String>,
22 pub metadata: Vec<TaskMetadataInput>,
23 pub available_at: Option<String>,
24 pub due_on: Option<String>,
25 pub is_epic: bool,
26}
27
28#[derive(Debug, Clone, Default)]
29pub enum TaskCreationUndo {
30 #[default]
31 None,
32 TuiTask,
33 TuiEpicChild {
34 epic_id: TaskId,
35 epic_display_ref: String,
36 },
37}
38
39#[derive(Debug, Clone)]
40pub struct TaskCreationOptions {
41 epic_id: Option<TaskId>,
42 undo: TaskCreationUndo,
43 create_missing_labels: bool,
44 require_existing_project: bool,
45 capture_undo_snapshot: bool,
46 require_existing_epic: bool,
47}
48
49impl TaskCreationOptions {
50 pub fn standalone(undo: TaskCreationUndo) -> Self {
51 Self {
52 epic_id: None,
53 undo,
54 create_missing_labels: false,
55 require_existing_project: false,
56 capture_undo_snapshot: false,
57 require_existing_epic: false,
58 }
59 }
60
61 pub fn for_epic(epic_id: TaskId, undo: TaskCreationUndo) -> Self {
62 Self {
63 epic_id: Some(epic_id),
64 undo,
65 create_missing_labels: false,
66 require_existing_project: false,
67 capture_undo_snapshot: false,
68 require_existing_epic: false,
69 }
70 }
71
72 pub fn with_create_missing_labels(mut self) -> Self {
73 self.create_missing_labels = true;
74 self
75 }
76
77 pub(crate) fn for_consumer_epic(epic_id: Option<TaskId>) -> Self {
78 Self {
79 epic_id,
80 undo: TaskCreationUndo::None,
81 create_missing_labels: false,
82 require_existing_project: true,
83 capture_undo_snapshot: false,
84 require_existing_epic: true,
85 }
86 }
87
88 pub fn for_consumer_capture() -> Self {
89 Self {
90 epic_id: None,
91 undo: TaskCreationUndo::None,
92 create_missing_labels: false,
93 require_existing_project: true,
94 capture_undo_snapshot: true,
95 require_existing_epic: false,
96 }
97 }
98}
99
100#[derive(Debug)]
101pub struct TaskOutcome {
102 pub task: Task,
103 pub create_change_id: Option<String>,
104 pub attachment_change_ids: Vec<String>,
105 pub undo_snapshot: Option<TaskUndoSnapshot>,
106}
107
108struct InsertedTask {
109 id: TaskId,
110 change_id: String,
111 project_key: String,
112 label_count: usize,
113 created_labels: Vec<CreatedLabel>,
114}
115
116#[derive(Debug, Clone)]
117pub struct TaskLabelSelection {
118 pub selected: Vec<String>,
119 pub partial: Vec<String>,
120}
121
122#[derive(Clone, Default)]
123pub struct TaskUpdate {
124 pub title: Option<String>,
125 pub description: Option<String>,
126 pub project: Option<String>,
127 pub status: Option<String>,
128 pub priority: Option<String>,
129 pub cycle_priority: Option<bool>,
130 pub available_at: Option<Option<String>>,
131 pub due_on: Option<Option<String>>,
132 pub deleted: Option<bool>,
133 pub is_epic: Option<bool>,
134 pub add_labels: Vec<String>,
135 pub remove_labels: Vec<String>,
136 pub set_metadata: Vec<TaskMetadataInput>,
137 pub remove_metadata: Vec<String>,
138 pub require_metadata_fields: Vec<(crate::ids::MetadataFieldId, String)>,
139 pub label_selection: Option<TaskLabelSelection>,
140 pub create_missing_labels: bool,
141}
142
143pub struct TaskUpdateOutcome {
144 pub task: Task,
145 pub changed: bool,
146}
147
148#[derive(Debug)]
149pub struct TaskMutationOutcome {
150 pub task: Task,
151 pub before: TaskUndoSnapshot,
152 pub after: TaskUndoSnapshot,
153 pub changed: bool,
154}
155
156#[derive(Debug)]
157pub struct TaskMutationReport {
158 pub outcomes: Vec<TaskMutationOutcome>,
159}
160
161impl TaskMutationReport {
162 pub fn changed_count(&self) -> usize {
163 self.outcomes
164 .iter()
165 .filter(|outcome| outcome.changed)
166 .count()
167 }
168}
169
170pub struct NoteEditOutcome {
171 #[allow(dead_code)]
172 pub task_id: TaskId,
173 #[allow(dead_code)]
174 pub note_id: String,
175 pub found: bool,
176 pub changed: bool,
177}
178
179pub struct NoteDeleteOutcome {
180 #[allow(dead_code)]
181 pub task_id: TaskId,
182 #[allow(dead_code)]
183 pub note_id: String,
184 pub changed: bool,
185}
186
187pub struct NoteOutcome {
188 #[allow(dead_code)]
189 pub task_id: TaskId,
190 pub note_id: String,
191 pub change_id: String,
192}
193
194pub(crate) use consumer::ConsumerTaskMutation;
195#[cfg(any(test, feature = "test-support"))]
196pub(crate) use creation::create_task;
197#[cfg(any(test, feature = "test-support"))]
198pub(crate) use mutation::update_task;
199pub(crate) use mutation::update_task_labels_in_workspace;
200#[cfg(test)]
201pub(in crate::operations) use notes::add_note_operation;