primitives.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{fmt, str::FromStr};
  19. use darkfi::{util::time::Timestamp, Error, Result};
  20. use crate::due_as_timestamp;
  21. pub enum State {
  22. Open,
  23. Start,
  24. Pause,
  25. Stop,
  26. }
  27. impl State {
  28. pub const fn is_start(&self) -> bool {
  29. matches!(*self, Self::Start)
  30. }
  31. pub const fn is_pause(&self) -> bool {
  32. matches!(*self, Self::Pause)
  33. }
  34. pub const fn is_stop(&self) -> bool {
  35. matches!(*self, Self::Stop)
  36. }
  37. }
  38. impl fmt::Display for State {
  39. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  40. match self {
  41. State::Open => write!(f, "open"),
  42. State::Start => write!(f, "start"),
  43. State::Stop => write!(f, "stop"),
  44. State::Pause => write!(f, "pause"),
  45. }
  46. }
  47. }
  48. impl FromStr for State {
  49. type Err = Error;
  50. fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
  51. let result = match s.to_lowercase().as_str() {
  52. "open" => State::Open,
  53. "stop" => State::Stop,
  54. "start" => State::Start,
  55. "pause" => State::Pause,
  56. _ => return Err(Error::ParseFailed("unable to parse state")),
  57. };
  58. Ok(result)
  59. }
  60. }
  61. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  62. pub struct BaseTask {
  63. pub title: String,
  64. pub tags: Vec<String>,
  65. pub desc: Option<String>,
  66. pub assign: Vec<String>,
  67. pub project: Vec<String>,
  68. pub due: Option<u64>,
  69. pub rank: Option<f32>,
  70. }
  71. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  72. pub struct TaskInfo {
  73. pub ref_id: String,
  74. pub workspace: String,
  75. pub id: u32,
  76. pub title: String,
  77. pub tags: Vec<String>,
  78. pub desc: String,
  79. pub owner: String,
  80. pub assign: Vec<String>,
  81. pub project: Vec<String>,
  82. pub due: Option<u64>,
  83. pub rank: Option<f32>,
  84. pub created_at: u64,
  85. pub state: String,
  86. pub events: Vec<TaskEvent>,
  87. pub comments: Vec<Comment>,
  88. }
  89. impl From<BaseTask> for TaskInfo {
  90. fn from(value: BaseTask) -> Self {
  91. Self {
  92. ref_id: String::default(),
  93. workspace: String::default(),
  94. id: u32::default(),
  95. title: value.title,
  96. tags: value.tags,
  97. desc: String::default(),
  98. owner: String::default(),
  99. assign: value.assign,
  100. project: value.project,
  101. due: value.due,
  102. rank: value.rank,
  103. created_at: u64::default(),
  104. state: String::default(),
  105. events: vec![],
  106. comments: vec![],
  107. }
  108. }
  109. }
  110. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  111. pub struct TaskEvent {
  112. pub action: String,
  113. pub author: String,
  114. pub content: String,
  115. pub timestamp: Timestamp,
  116. }
  117. impl std::fmt::Display for TaskEvent {
  118. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  119. write!(f, "action: {}, timestamp: {}", self.action, self.timestamp)
  120. }
  121. }
  122. impl Default for TaskEvent {
  123. fn default() -> Self {
  124. Self {
  125. action: State::Open.to_string(),
  126. author: "".to_string(),
  127. content: "".to_string(),
  128. timestamp: Timestamp::current_time(),
  129. }
  130. }
  131. }
  132. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  133. pub struct Comment {
  134. content: String,
  135. author: String,
  136. timestamp: Timestamp,
  137. }
  138. impl std::fmt::Display for Comment {
  139. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  140. write!(f, "{} author: {}, content: {} ", self.timestamp, self.author, self.content)
  141. }
  142. }
  143. pub fn task_from_cli(values: Vec<String>) -> Result<BaseTask> {
  144. let mut title = String::new();
  145. let mut tags = vec![];
  146. let mut desc = None;
  147. let mut project = vec![];
  148. let mut assign = vec![];
  149. let mut due = None;
  150. let mut rank = None;
  151. for val in values {
  152. let field: Vec<&str> = val.split(':').collect();
  153. if field.len() == 1 {
  154. if field[0].starts_with('+') || field[0].starts_with('-') {
  155. tags.push(field[0].into());
  156. continue
  157. }
  158. title.push_str(field[0]);
  159. title.push(' ');
  160. continue
  161. }
  162. if field.len() != 2 {
  163. continue
  164. }
  165. if field[0] == "project" {
  166. project = field[1].split(',').map(|s| s.into()).collect();
  167. }
  168. if field[0] == "desc" {
  169. desc = Some(field[1].into());
  170. }
  171. if field[0] == "assign" {
  172. assign = field[1].split(',').map(|s| s.into()).collect();
  173. }
  174. if field[0] == "due" {
  175. due = due_as_timestamp(field[1])
  176. }
  177. if field[0] == "rank" {
  178. rank = Some(field[1].parse::<f32>()?);
  179. }
  180. }
  181. let title = title.trim().into();
  182. Ok(BaseTask { title, tags, desc, project, assign, due, rank })
  183. }