Skip to main content

aven_core/operations/
tasks.rs

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;