task_info.rs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. use std::{
  2. io,
  3. path::{Path, PathBuf},
  4. };
  5. use log::debug;
  6. use serde::{Deserialize, Serialize};
  7. use crate::{
  8. error::{TaudError, TaudResult},
  9. month_tasks::MonthTasks,
  10. util::{find_free_id, get_current_time, load, random_ref_id, save, Timestamp},
  11. };
  12. use darkfi::util::serial::{Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt};
  13. #[derive(Clone, Debug, Serialize, Deserialize, SerialEncodable, SerialDecodable, PartialEq)]
  14. struct TaskEvent {
  15. action: String,
  16. timestamp: Timestamp,
  17. }
  18. impl TaskEvent {
  19. fn new(action: String) -> Self {
  20. Self { action, timestamp: get_current_time() }
  21. }
  22. }
  23. #[derive(Clone, Debug, Serialize, Deserialize, SerialDecodable, SerialEncodable, PartialEq)]
  24. pub struct Comment {
  25. content: String,
  26. author: String,
  27. timestamp: Timestamp,
  28. }
  29. impl Comment {
  30. pub fn new(content: &str, author: &str) -> Self {
  31. Self { content: content.into(), author: author.into(), timestamp: get_current_time() }
  32. }
  33. }
  34. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
  35. pub struct TaskEvents(Vec<TaskEvent>);
  36. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
  37. pub struct TaskComments(Vec<Comment>);
  38. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
  39. pub struct TaskProjects(Vec<String>);
  40. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
  41. pub struct TaskAssigns(Vec<String>);
  42. #[derive(Clone, Debug, Serialize, Deserialize, SerialEncodable, SerialDecodable, PartialEq)]
  43. pub struct TaskInfo {
  44. pub(crate) ref_id: String,
  45. id: u32,
  46. title: String,
  47. desc: String,
  48. assign: TaskAssigns,
  49. project: TaskProjects,
  50. due: Option<Timestamp>,
  51. rank: f32,
  52. created_at: Timestamp,
  53. events: TaskEvents,
  54. comments: TaskComments,
  55. }
  56. impl TaskInfo {
  57. pub fn new(
  58. title: &str,
  59. desc: &str,
  60. due: Option<Timestamp>,
  61. rank: f32,
  62. dataset_path: &Path,
  63. ) -> TaudResult<Self> {
  64. // generate ref_id
  65. let ref_id = random_ref_id();
  66. let created_at: Timestamp = get_current_time();
  67. let task_ids: Vec<u32> =
  68. MonthTasks::load_current_open_tasks(dataset_path)?.into_iter().map(|t| t.id).collect();
  69. let id: u32 = find_free_id(&task_ids);
  70. if let Some(d) = &due {
  71. if *d < get_current_time() {
  72. return Err(TaudError::InvalidDueTime)
  73. }
  74. }
  75. Ok(Self {
  76. ref_id,
  77. id,
  78. title: title.into(),
  79. desc: desc.into(),
  80. assign: TaskAssigns(vec![]),
  81. project: TaskProjects(vec![]),
  82. due,
  83. rank,
  84. created_at,
  85. comments: TaskComments(vec![]),
  86. events: TaskEvents(vec![]),
  87. })
  88. }
  89. pub fn load(ref_id: &str, dataset_path: &Path) -> TaudResult<Self> {
  90. debug!(target: "tau", "TaskInfo::load()");
  91. let task = load::<Self>(&Self::get_path(ref_id, dataset_path))?;
  92. Ok(task)
  93. }
  94. pub fn save(&self, dataset_path: &Path) -> TaudResult<()> {
  95. debug!(target: "tau", "TaskInfo::save()");
  96. save::<Self>(&Self::get_path(&self.ref_id, dataset_path), self)
  97. .map_err(TaudError::Darkfi)?;
  98. if self.get_state() == "stop" {
  99. self.deactivate(dataset_path)?;
  100. } else {
  101. self.activate(dataset_path)?;
  102. }
  103. Ok(())
  104. }
  105. pub fn activate(&self, path: &Path) -> TaudResult<()> {
  106. debug!(target: "tau", "TaskInfo::activate()");
  107. let mut mt = MonthTasks::load_or_create(&self.created_at, path)?;
  108. mt.add(&self.ref_id);
  109. mt.save(path)
  110. }
  111. pub fn deactivate(&self, path: &Path) -> TaudResult<()> {
  112. debug!(target: "tau", "TaskInfo::deactivate()");
  113. let mut mt = MonthTasks::load_or_create(&self.created_at, path)?;
  114. mt.remove(&self.ref_id);
  115. mt.save(path)
  116. }
  117. pub fn get_state(&self) -> String {
  118. debug!(target: "tau", "TaskInfo::get_state()");
  119. if let Some(ev) = self.events.0.last() {
  120. ev.action.clone()
  121. } else {
  122. "open".into()
  123. }
  124. }
  125. fn get_path(ref_id: &str, dataset_path: &Path) -> PathBuf {
  126. debug!(target: "tau", "TaskInfo::get_path()");
  127. dataset_path.join("task").join(ref_id)
  128. }
  129. pub fn get_id(&self) -> u32 {
  130. debug!(target: "tau", "TaskInfo::get_id()");
  131. self.id
  132. }
  133. pub fn set_title(&mut self, title: &str) {
  134. debug!(target: "tau", "TaskInfo::set_title()");
  135. self.title = title.into();
  136. }
  137. pub fn set_desc(&mut self, desc: &str) {
  138. debug!(target: "tau", "TaskInfo::set_desc()");
  139. self.desc = desc.into();
  140. }
  141. pub fn set_assign(&mut self, assign: &[String]) {
  142. debug!(target: "tau", "TaskInfo::set_assign()");
  143. self.assign = TaskAssigns(assign.to_owned());
  144. }
  145. pub fn set_project(&mut self, project: &[String]) {
  146. debug!(target: "tau", "TaskInfo::set_project()");
  147. self.project = TaskProjects(project.to_owned());
  148. }
  149. pub fn set_comment(&mut self, c: Comment) {
  150. debug!(target: "tau", "TaskInfo::set_comment()");
  151. self.comments.0.push(c);
  152. }
  153. pub fn set_rank(&mut self, r: f32) {
  154. debug!(target: "tau", "TaskInfo::set_rank()");
  155. self.rank = r;
  156. }
  157. pub fn set_due(&mut self, d: Option<Timestamp>) {
  158. debug!(target: "tau", "TaskInfo::set_due()");
  159. self.due = d;
  160. }
  161. pub fn set_state(&mut self, action: &str) {
  162. debug!(target: "tau", "TaskInfo::set_state()");
  163. if self.get_state() == action {
  164. return
  165. }
  166. self.events.0.push(TaskEvent::new(action.into()));
  167. }
  168. }
  169. impl Encodable for TaskEvents {
  170. fn encode<S: io::Write>(&self, s: S) -> darkfi::Result<usize> {
  171. encode_vec(&self.0, s)
  172. }
  173. }
  174. impl Decodable for TaskEvents {
  175. fn decode<D: io::Read>(d: D) -> darkfi::Result<Self> {
  176. Ok(Self(decode_vec(d)?))
  177. }
  178. }
  179. impl Encodable for TaskComments {
  180. fn encode<S: io::Write>(&self, s: S) -> darkfi::Result<usize> {
  181. encode_vec(&self.0, s)
  182. }
  183. }
  184. impl Decodable for TaskComments {
  185. fn decode<D: io::Read>(d: D) -> darkfi::Result<Self> {
  186. Ok(Self(decode_vec(d)?))
  187. }
  188. }
  189. impl Encodable for TaskProjects {
  190. fn encode<S: io::Write>(&self, s: S) -> darkfi::Result<usize> {
  191. encode_vec(&self.0, s)
  192. }
  193. }
  194. impl Decodable for TaskProjects {
  195. fn decode<D: io::Read>(d: D) -> darkfi::Result<Self> {
  196. Ok(Self(decode_vec(d)?))
  197. }
  198. }
  199. impl Encodable for TaskAssigns {
  200. fn encode<S: io::Write>(&self, s: S) -> darkfi::Result<usize> {
  201. encode_vec(&self.0, s)
  202. }
  203. }
  204. impl Decodable for TaskAssigns {
  205. fn decode<D: io::Read>(d: D) -> darkfi::Result<Self> {
  206. Ok(Self(decode_vec(d)?))
  207. }
  208. }
  209. fn encode_vec<T: Encodable, S: io::Write>(vec: &[T], mut s: S) -> darkfi::Result<usize> {
  210. let mut len = 0;
  211. len += VarInt(vec.len() as u64).encode(&mut s)?;
  212. for c in vec.iter() {
  213. len += c.encode(&mut s)?;
  214. }
  215. Ok(len)
  216. }
  217. fn decode_vec<T: Decodable, D: io::Read>(mut d: D) -> darkfi::Result<Vec<T>> {
  218. let len = VarInt::decode(&mut d)?.0;
  219. let mut ret = Vec::with_capacity(len as usize);
  220. for _ in 0..len {
  221. ret.push(Decodable::decode(&mut d)?);
  222. }
  223. Ok(ret)
  224. }