month_tasks.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. use std::{
  2. fs, io,
  3. path::{Path, PathBuf},
  4. };
  5. use chrono::{TimeZone, Utc};
  6. use log::debug;
  7. use serde::{Deserialize, Serialize};
  8. use darkfi::util::{
  9. file::{load_json_file, save_json_file},
  10. Timestamp,
  11. };
  12. use crate::{
  13. error::{TaudError, TaudResult},
  14. task_info::TaskInfo,
  15. };
  16. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
  17. pub struct MonthTasks {
  18. created_at: Timestamp,
  19. task_tks: Vec<String>,
  20. }
  21. impl MonthTasks {
  22. pub fn new(task_tks: &[String]) -> Self {
  23. Self { created_at: Timestamp::current_time(), task_tks: task_tks.to_owned() }
  24. }
  25. pub fn add(&mut self, ref_id: &str) {
  26. debug!(target: "tau", "MonthTasks::add()");
  27. if !self.task_tks.contains(&ref_id.into()) {
  28. self.task_tks.push(ref_id.into());
  29. }
  30. }
  31. pub fn objects(&self, dataset_path: &Path) -> TaudResult<Vec<TaskInfo>> {
  32. debug!(target: "tau", "MonthTasks::objects()");
  33. let mut tks: Vec<TaskInfo> = vec![];
  34. for ref_id in self.task_tks.iter() {
  35. tks.push(TaskInfo::load(ref_id, dataset_path)?);
  36. }
  37. Ok(tks)
  38. }
  39. pub fn remove(&mut self, ref_id: &str) {
  40. debug!(target: "tau", "MonthTasks::remove()");
  41. if let Some(index) = self.task_tks.iter().position(|t| *t == ref_id) {
  42. self.task_tks.remove(index);
  43. }
  44. }
  45. pub fn set_date(&mut self, date: &Timestamp) {
  46. debug!(target: "tau", "MonthTasks::set_date()");
  47. self.created_at = *date;
  48. }
  49. fn get_path(date: &Timestamp, dataset_path: &Path) -> PathBuf {
  50. debug!(target: "tau", "MonthTasks::get_path()");
  51. dataset_path.join("month").join(Utc.timestamp(date.0, 0).format("%m%y").to_string())
  52. }
  53. pub fn save(&self, dataset_path: &Path) -> TaudResult<()> {
  54. debug!(target: "tau", "MonthTasks::save()");
  55. save_json_file::<Self>(&Self::get_path(&self.created_at, dataset_path), self)
  56. .map_err(TaudError::Darkfi)
  57. }
  58. fn get_all(dataset_path: &Path) -> io::Result<Vec<PathBuf>> {
  59. debug!(target: "tau", "MonthTasks::get_all()");
  60. let mut entries = fs::read_dir(dataset_path.join("month"))?
  61. .map(|res| res.map(|e| e.path()))
  62. .collect::<Result<Vec<_>, io::Error>>()?;
  63. entries.sort();
  64. Ok(entries)
  65. }
  66. fn create(date: &Timestamp, dataset_path: &Path) -> TaudResult<Self> {
  67. debug!(target: "tau", "MonthTasks::create()");
  68. let mut mt = Self::new(&[]);
  69. mt.set_date(date);
  70. mt.save(dataset_path)?;
  71. Ok(mt)
  72. }
  73. pub fn load_or_create(date: Option<&Timestamp>, dataset_path: &Path) -> TaudResult<Self> {
  74. debug!(target: "tau", "MonthTasks::load_or_create()");
  75. // if a date is given we load that date's month tasks
  76. // if not, we load tasks from all months
  77. match date {
  78. Some(date) => match load_json_file::<Self>(&Self::get_path(date, dataset_path)) {
  79. Ok(mt) => Ok(mt),
  80. Err(_) => Self::create(date, dataset_path),
  81. },
  82. None => {
  83. let path_all = match Self::get_all(dataset_path) {
  84. Ok(t) => t,
  85. Err(_) => vec![],
  86. };
  87. let mut loaded_mt = Self::new(&[]);
  88. for path in path_all {
  89. let mt = load_json_file::<Self>(&path)?;
  90. loaded_mt.created_at = mt.created_at;
  91. for tks in mt.task_tks {
  92. if !loaded_mt.task_tks.contains(&tks) {
  93. loaded_mt.task_tks.push(tks)
  94. }
  95. }
  96. }
  97. Ok(loaded_mt)
  98. }
  99. }
  100. }
  101. pub fn load_current_open_tasks(dataset_path: &Path, ws: String) -> TaudResult<Vec<TaskInfo>> {
  102. let mt = Self::load_or_create(None, dataset_path)?;
  103. Ok(mt
  104. .objects(dataset_path)?
  105. .into_iter()
  106. .filter(|t| t.get_state() != "stop")
  107. .filter(|t| t.workspace == ws)
  108. .collect())
  109. }
  110. }
  111. #[cfg(test)]
  112. mod tests {
  113. use std::{
  114. fs::{create_dir_all, remove_dir_all},
  115. path::PathBuf,
  116. };
  117. use super::*;
  118. use darkfi::Result;
  119. const TEST_DATA_PATH: &str = "/tmp/test_tau_data";
  120. fn get_path() -> Result<PathBuf> {
  121. remove_dir_all(TEST_DATA_PATH).ok();
  122. let path = PathBuf::from(TEST_DATA_PATH);
  123. // mkdir dataset_path if not exists
  124. create_dir_all(path.join("month"))?;
  125. create_dir_all(path.join("task"))?;
  126. Ok(path)
  127. }
  128. #[test]
  129. fn load_and_save_tasks() -> TaudResult<()> {
  130. let dataset_path = get_path()?;
  131. // load and save TaskInfo
  132. ///////////////////////
  133. let mut task = TaskInfo::new(
  134. "darkfi".to_string(),
  135. "test_title",
  136. "test_desc",
  137. "NICKNAME",
  138. None,
  139. 0.0,
  140. &dataset_path,
  141. )?;
  142. task.save(&dataset_path)?;
  143. let t_load = TaskInfo::load(&task.ref_id, &dataset_path)?;
  144. assert_eq!(task, t_load);
  145. task.set_title("test_title_2");
  146. task.save(&dataset_path)?;
  147. let t_load = TaskInfo::load(&task.ref_id, &dataset_path)?;
  148. assert_eq!(task, t_load);
  149. // load and save MonthTasks
  150. ///////////////////////
  151. let task_tks = vec![];
  152. let mut mt = MonthTasks::new(&task_tks);
  153. mt.save(&dataset_path)?;
  154. let mt_load = MonthTasks::load_or_create(Some(&Timestamp::current_time()), &dataset_path)?;
  155. assert_eq!(mt, mt_load);
  156. mt.add(&task.ref_id);
  157. mt.save(&dataset_path)?;
  158. let mt_load = MonthTasks::load_or_create(Some(&Timestamp::current_time()), &dataset_path)?;
  159. assert_eq!(mt, mt_load);
  160. // activate task
  161. ///////////////////////
  162. let task = TaskInfo::new(
  163. "darkfi".to_string(),
  164. "test_title_3",
  165. "test_desc",
  166. "NICKNAME",
  167. None,
  168. 0.0,
  169. &dataset_path,
  170. )?;
  171. task.save(&dataset_path)?;
  172. let mt_load = MonthTasks::load_or_create(Some(&Timestamp::current_time()), &dataset_path)?;
  173. assert!(mt_load.task_tks.contains(&task.ref_id));
  174. remove_dir_all(TEST_DATA_PATH).ok();
  175. Ok(())
  176. }
  177. }