Skip to main content

aven_core/operations/
tasks.rs

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