Dastan-glitch 3 лет назад
Родитель
Сommit
99cf6f7789

+ 3 - 0
bin/tau/tau-cli/src/filter.rs

@@ -34,6 +34,9 @@ pub fn apply_filter(tasks: &mut Vec<TaskInfo>, filter: &str) {
             }
         }
 
+        // Filter by month
+        _ if filter.starts_with('+') => tasks.retain(|task| task.tags.contains(&filter.into())),
+
         // Filter by month
         _ if filter.contains("month:") => {
             let kv: Vec<&str> = filter.split(':').collect();

+ 1 - 0
bin/tau/tau-cli/src/main.rs

@@ -76,6 +76,7 @@ enum TauSubcommand {
 
     /// Modify/Edit an existing task.
     Modify {
+        #[clap(allow_hyphen_values = true)]
         /// Values (e.g. project:blockchain).
         values: Vec<String>,
     },

+ 9 - 2
bin/tau/tau-cli/src/primitives.rs

@@ -52,6 +52,7 @@ impl FromStr for State {
 #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
 pub struct BaseTask {
     pub title: String,
+    pub tags: Vec<String>,
     pub desc: Option<String>,
     pub assign: Vec<String>,
     pub project: Vec<String>,
@@ -65,6 +66,7 @@ pub struct TaskInfo {
     pub workspace: String,
     pub id: u32,
     pub title: String,
+    pub tags: Vec<String>,
     pub desc: String,
     pub owner: String,
     pub assign: Vec<String>,
@@ -117,6 +119,7 @@ impl std::fmt::Display for Comment {
 
 pub fn task_from_cli(values: Vec<String>) -> Result<BaseTask> {
     let mut title = String::new();
+    let mut tags = vec![];
     let mut desc = None;
     let mut project = vec![];
     let mut assign = vec![];
@@ -126,6 +129,10 @@ pub fn task_from_cli(values: Vec<String>) -> Result<BaseTask> {
     for val in values {
         let field: Vec<&str> = val.split(':').collect();
         if field.len() == 1 {
+            if field[0].starts_with('+') || field[0].starts_with('-') {
+                tags.push(field[0].into());
+                continue
+            }
             title.push_str(field[0]);
             title.push(' ');
             continue
@@ -155,6 +162,6 @@ pub fn task_from_cli(values: Vec<String>) -> Result<BaseTask> {
             rank = Some(field[1].parse::<f32>()?);
         }
     }
-    let title = title.trim().into();
-    Ok(BaseTask { title, desc, project, assign, due, rank })
+
+    Ok(BaseTask { title, tags, desc, project, assign, due, rank })
 }

+ 15 - 8
bin/tau/tau-cli/src/view.rs

@@ -26,7 +26,7 @@ pub fn print_task_list(tasks: Vec<TaskInfo>, ws: String) -> Result<()> {
             .separators(&[LinePosition::Title], LineSeparator::new('-', ' ', ' ', ' '))
             .build(),
     );
-    table.set_titles(row!["ID", "Title", "Project", "Assigned", "Due", "Rank"]);
+    table.set_titles(row!["ID", "Title", "Tags", "Project", "Assigned", "Due", "Rank"]);
 
     // group tasks by state.
     tasks.sort_by_key(|task| task.state.clone());
@@ -66,10 +66,16 @@ pub fn print_task_list(tasks: Vec<TaskInfo>, ws: String) -> Result<()> {
         };
 
         let rank = if let Some(r) = task.rank { r.to_string() } else { "".to_string() };
+        let mut print_tags = vec![];
+        for tag in &task.tags {
+            let t = tag.replace('+', "");
+            print_tags.push(t)
+        }
 
         table.add_row(Row::new(vec![
             Cell::new(&task.id.to_string()).style_spec(gen_style),
             Cell::new(&task.title).style_spec(gen_style),
+            Cell::new(&print_tags.join(", ")).style_spec(gen_style),
             Cell::new(&task.project.join(", ")).style_spec(gen_style),
             Cell::new(&task.assign.join(", ")).style_spec(gen_style),
             Cell::new(&timestamp_to_date(task.due.unwrap_or(0), DateFormat::Date))
@@ -109,13 +115,14 @@ pub fn print_task_info(taskinfo: TaskInfo) -> Result<()> {
         [Bd =>"id", &taskinfo.id.to_string()],
         ["owner", &taskinfo.owner],
         [Bd =>"title", &taskinfo.title],
-        ["desc", &taskinfo.desc.to_string()],
-        [Bd =>"assign", taskinfo.assign.join(", ")],
-        ["project", taskinfo.project.join(", ")],
-        [Bd =>"due", due],
-        ["rank", rank],
-        [Bd =>"created_at", created_at],
-        ["current_state", &taskinfo.state]);
+        ["tags", &taskinfo.tags.join(", ")],
+        [Bd =>"desc", &taskinfo.desc.to_string()],
+        ["assign", taskinfo.assign.join(", ")],
+        [Bd =>"project", taskinfo.project.join(", ")],
+        ["due", due],
+        [Bd =>"rank", rank],
+        ["created_at", created_at],
+        [Bd =>"current_state", &taskinfo.state]);
 
     table.set_format(
         FormatBuilder::new()

+ 15 - 0
bin/tau/taud/src/jsonrpc.rs

@@ -36,6 +36,7 @@ pub struct JsonRpcInterface {
 #[derive(Clone, Debug, Serialize, Deserialize)]
 struct BaseTaskInfo {
     title: String,
+    tags: Vec<String>,
     desc: String,
     assign: Vec<String>,
     project: Vec<String>,
@@ -133,6 +134,7 @@ impl JsonRpcInterface {
         )?;
         new_task.set_project(&task.project);
         new_task.set_assign(&task.assign);
+        new_task.set_tags(&task.tags);
 
         self.notify_queue_sender.send(new_task).await.map_err(Error::from)?;
         Ok(json!(true))
@@ -429,6 +431,19 @@ impl JsonRpcInterface {
             }
         }
 
+        if fields.contains_key("tags") {
+            println!("fields: {:?}", fields);
+            let tags = fields.get("tags").unwrap().clone();
+            println!("tags: {:?}", tags);
+
+            let tags: Vec<String> = serde_json::from_value(tags)?;
+            println!("vec tags: {:?}", tags);
+            if !tags.is_empty() {
+                task.set_tags(&tags);
+                // task.set_event("project", &self.nickname, &tags.join(", "));
+            }
+        }
+
         Ok(task)
     }
 }

+ 30 - 0
bin/tau/taud/src/task_info.rs

@@ -58,6 +58,8 @@ pub struct TaskComments(Vec<Comment>);
 pub struct TaskProjects(Vec<String>);
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
 pub struct TaskAssigns(Vec<String>);
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
+pub struct TaskTags(Vec<String>);
 
 #[derive(Clone, Debug, Serialize, Deserialize, SerialEncodable, SerialDecodable, PartialEq)]
 pub struct TaskInfo {
@@ -65,6 +67,7 @@ pub struct TaskInfo {
     pub(crate) workspace: String,
     id: u32,
     title: String,
+    tags: TaskTags,
     desc: String,
     owner: String,
     assign: TaskAssigns,
@@ -113,6 +116,7 @@ impl TaskInfo {
             title: title.into(),
             desc: desc.into(),
             owner: owner.into(),
+            tags: TaskTags(vec![]),
             assign: TaskAssigns(vec![]),
             project: TaskProjects(vec![]),
             due,
@@ -183,6 +187,20 @@ impl TaskInfo {
         self.desc = desc.into();
     }
 
+    pub fn set_tags(&mut self, tags: &[String]) {
+        debug!(target: "tau", "TaskInfo::set_tags()");
+        println!("tags: {:?}", tags);
+        for tag in tags.iter() {
+            if tag.starts_with('+') {
+                self.tags.0.push(tag.to_string());
+            }
+            if tag.starts_with('-') {
+                let t = tag.replace('-', "+");
+                self.tags.0.retain(|tag| tag != &t);
+            }
+        }
+    }
+
     pub fn set_assign(&mut self, assign: &[String]) {
         debug!(target: "tau", "TaskInfo::set_assign()");
         self.assign = TaskAssigns(assign.to_owned());
@@ -270,6 +288,18 @@ impl Decodable for TaskAssigns {
     }
 }
 
+impl Encodable for TaskTags {
+    fn encode<S: io::Write>(&self, s: S) -> darkfi::Result<usize> {
+        encode_vec(&self.0, s)
+    }
+}
+
+impl Decodable for TaskTags {
+    fn decode<D: io::Read>(d: D) -> darkfi::Result<Self> {
+        Ok(Self(decode_vec(d)?))
+    }
+}
+
 fn encode_vec<T: Encodable, S: io::Write>(vec: &[T], mut s: S) -> darkfi::Result<usize> {
     let mut len = 0;
     len += VarInt(vec.len() as u64).encode(&mut s)?;