primitives.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. use std::{fmt, str::FromStr};
  2. use darkfi::{util::Timestamp, Error, Result};
  3. use crate::due_as_timestamp;
  4. pub enum State {
  5. Open,
  6. Start,
  7. Pause,
  8. Stop,
  9. }
  10. impl State {
  11. pub const fn is_start(&self) -> bool {
  12. matches!(*self, Self::Start)
  13. }
  14. pub const fn is_pause(&self) -> bool {
  15. matches!(*self, Self::Pause)
  16. }
  17. pub const fn is_stop(&self) -> bool {
  18. matches!(*self, Self::Stop)
  19. }
  20. }
  21. impl fmt::Display for State {
  22. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  23. match self {
  24. State::Open => write!(f, "open"),
  25. State::Start => write!(f, "start"),
  26. State::Stop => write!(f, "stop"),
  27. State::Pause => write!(f, "pause"),
  28. }
  29. }
  30. }
  31. impl FromStr for State {
  32. type Err = Error;
  33. fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
  34. let result = match s.to_lowercase().as_str() {
  35. "open" => State::Open,
  36. "stop" => State::Stop,
  37. "start" => State::Start,
  38. "pause" => State::Pause,
  39. _ => return Err(Error::ParseFailed("unable to parse state")),
  40. };
  41. Ok(result)
  42. }
  43. }
  44. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  45. pub struct BaseTask {
  46. pub title: String,
  47. pub desc: Option<String>,
  48. pub assign: Vec<String>,
  49. pub project: Vec<String>,
  50. pub due: Option<i64>,
  51. pub rank: Option<f32>,
  52. }
  53. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  54. pub struct TaskInfo {
  55. pub ref_id: String,
  56. pub workspace: String,
  57. pub id: u32,
  58. pub title: String,
  59. pub desc: String,
  60. pub owner: String,
  61. pub assign: Vec<String>,
  62. pub project: Vec<String>,
  63. pub due: Option<i64>,
  64. pub rank: Option<f32>,
  65. pub created_at: i64,
  66. pub state: String,
  67. pub events: Vec<TaskEvent>,
  68. pub comments: Vec<Comment>,
  69. }
  70. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  71. pub struct TaskEvent {
  72. pub action: String,
  73. pub author: String,
  74. pub content: String,
  75. pub timestamp: Timestamp,
  76. }
  77. impl std::fmt::Display for TaskEvent {
  78. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  79. write!(f, "action: {}, timestamp: {}", self.action, self.timestamp)
  80. }
  81. }
  82. impl Default for TaskEvent {
  83. fn default() -> Self {
  84. Self {
  85. action: State::Open.to_string(),
  86. author: "".to_string(),
  87. content: "".to_string(),
  88. timestamp: Timestamp::current_time(),
  89. }
  90. }
  91. }
  92. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
  93. pub struct Comment {
  94. content: String,
  95. author: String,
  96. timestamp: Timestamp,
  97. }
  98. impl std::fmt::Display for Comment {
  99. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  100. write!(f, "{} author: {}, content: {} ", self.timestamp, self.author, self.content)
  101. }
  102. }
  103. pub fn task_from_cli(values: Vec<String>) -> Result<BaseTask> {
  104. let mut title = String::new();
  105. let mut desc = None;
  106. let mut project = vec![];
  107. let mut assign = vec![];
  108. let mut due = None;
  109. let mut rank = None;
  110. for val in values {
  111. let field: Vec<&str> = val.split(':').collect();
  112. if field.len() == 1 {
  113. title.push_str(field[0]);
  114. title.push(' ');
  115. continue
  116. }
  117. if field.len() != 2 {
  118. continue
  119. }
  120. if field[0] == "project" {
  121. project = field[1].split(',').map(|s| s.into()).collect();
  122. }
  123. if field[0] == "desc" {
  124. desc = Some(field[1].into());
  125. }
  126. if field[0] == "assign" {
  127. assign = field[1].split(',').map(|s| s.into()).collect();
  128. }
  129. if field[0] == "due" {
  130. due = due_as_timestamp(field[1])
  131. }
  132. if field[0] == "rank" {
  133. rank = Some(field[1].parse::<f32>()?);
  134. }
  135. }
  136. let title = title.trim().into();
  137. Ok(BaseTask { title, desc, project, assign, due, rank })
  138. }