1use serde::{Deserialize, Serialize};
2use ts_rs::TS;
3
4use crate::{TaskId, Status, Task, ColumnRef};
5
6#[derive(Debug, Clone, Serialize, Deserialize, TS)]
7#[ts(export)]
8pub struct TaskOp {
9 pub task_id: TaskId,
10 pub operation: Operation,
11 pub timestamp: u64,
12 pub client_id: u64,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize, TS)]
16#[ts(export)]
17pub enum Operation {
18 Create {
19 title: String,
20 column: String,
21 },
22 SetStatus {
23 old: Status,
24 new: Status,
25 },
26 SetTitle {
27 old: String,
28 new: String,
29 },
30 SetMetadata {
31 key: String,
32 #[ts(type = "unknown | null")]
33 old: Option<serde_json::Value>,
34 #[ts(type = "unknown | null")]
35 new: Option<serde_json::Value>,
36 },
37 AddDependency {
38 dependency: TaskId,
39 },
40 RemoveDependency {
41 dependency: TaskId,
42 },
43 Move {
44 from_column: String,
45 to_column: String,
46 },
47 Delete,
48}
49
50impl Operation {
51 pub fn apply_to_task(&self, task: &mut Task) {
52 let now = chrono::Utc::now();
53 match self {
54 Operation::SetTitle { old: _, new } => {
55 task.title = new.clone();
56 task.updated_at = now;
57 }
58 Operation::SetStatus { old: _, new } => {
59 task.status = *new;
60 task.updated_at = now;
61 }
62 Operation::SetMetadata { key, old: _, new } => {
63 match new {
64 Some(value) => task.metadata.set(key, value.clone()),
65 None => task.metadata.remove(key),
66 }
67 task.updated_at = now;
68 }
69 Operation::AddDependency { dependency } => {
70 if !task.dependencies.contains(dependency) {
71 task.dependencies.push(dependency.clone());
72 task.updated_at = now;
73 }
74 }
75 Operation::RemoveDependency { dependency } => {
76 let before = task.dependencies.len();
77 task.dependencies.retain(|d| d != dependency);
78 if task.dependencies.len() != before {
79 task.updated_at = now;
80 }
81 }
82 Operation::Move { from_column: _, to_column } => {
83 task.column = ColumnRef::Name(to_column.clone());
84 task.updated_at = now;
85 }
86 Operation::Create { .. } | Operation::Delete => {}
87 }
88 }
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, TS)]
92#[ts(export)]
93pub struct OperationId {
94 pub client_id: u64,
95 pub sequence: u64,
96}