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