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        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;