main.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. use clap::{CommandFactory, Parser};
  2. use log::error;
  3. use prettytable::{cell, format, row, table};
  4. use serde_json::{json, Value};
  5. use simplelog::{ColorChoice, TermLogger, TerminalMode};
  6. use darkfi::{
  7. util::{
  8. cli::{log_config, spawn_config, Config},
  9. path::get_config_path,
  10. },
  11. Result,
  12. };
  13. mod jsonrpc;
  14. mod util;
  15. use crate::{
  16. jsonrpc::{add, get_by_id, get_state, list, set_comment, set_state, update},
  17. util::{
  18. desc_in_editor, due_as_timestamp, get_comments, get_events, get_from_task, list_tasks,
  19. set_title, timestamp_to_date, CliTau, CliTauSubCommands, TaskInfo, TauConfig,
  20. CONFIG_FILE_CONTENTS,
  21. },
  22. };
  23. async fn start(options: CliTau, config: TauConfig) -> Result<()> {
  24. let rpc_addr = &format!("tcp://{}", &config.rpc_listen.clone());
  25. if !options.filter.is_empty() {
  26. let rep = list(rpc_addr, json!([])).await?;
  27. list_tasks(rep, options.filter)?;
  28. } else {
  29. match options.command {
  30. Some(CliTauSubCommands::Add { title, desc, assign, project, due, rank }) => {
  31. let title = match title {
  32. Some(t) => t,
  33. None => set_title()?,
  34. };
  35. let desc = match desc {
  36. Some(d) => Some(d),
  37. None => desc_in_editor()?,
  38. };
  39. let assign: Vec<String> = match assign {
  40. Some(a) => a.split(',').map(|s| s.into()).collect(),
  41. None => vec![],
  42. };
  43. let project: Vec<String> = match project {
  44. Some(p) => p.split(',').map(|s| s.into()).collect(),
  45. None => vec![],
  46. };
  47. let due = match due {
  48. Some(d) => due_as_timestamp(&d),
  49. None => None,
  50. };
  51. let rank = rank.unwrap_or(0.0);
  52. add(
  53. rpc_addr,
  54. json!([{"title": title, "desc": desc, "assign": assign, "project": project, "due": due, "rank": rank}]),
  55. )
  56. .await?;
  57. }
  58. Some(CliTauSubCommands::Update { id, key, value }) => {
  59. let value = value.as_str().trim();
  60. let updated_value: Value = match key.as_str() {
  61. "due" => {
  62. json!(due_as_timestamp(value))
  63. }
  64. "rank" => {
  65. json!(value.parse::<f32>()?)
  66. }
  67. "project" | "assign" => {
  68. json!(value.split(',').collect::<Vec<&str>>())
  69. }
  70. _ => {
  71. json!(value)
  72. }
  73. };
  74. update(rpc_addr, id, json!({ key: updated_value })).await?;
  75. }
  76. Some(CliTauSubCommands::SetState { id, state }) => {
  77. if state.as_str() == "open" {
  78. set_state(rpc_addr, id, state.trim()).await?;
  79. } else if state.as_str() == "pause" {
  80. set_state(rpc_addr, id, state.trim()).await?;
  81. } else if state.as_str() == "stop" {
  82. set_state(rpc_addr, id, state.trim()).await?;
  83. } else {
  84. error!("Task state could only be one of three states: open, pause or stop");
  85. }
  86. }
  87. Some(CliTauSubCommands::GetState { id }) => {
  88. let state = get_state(rpc_addr, id).await?;
  89. println!("Task with id {} is: {}", id, state);
  90. }
  91. Some(CliTauSubCommands::SetComment { id, author, content }) => {
  92. set_comment(rpc_addr, id, author.trim(), content.trim()).await?;
  93. }
  94. Some(CliTauSubCommands::GetComment { id }) => {
  95. let rep = get_by_id(rpc_addr, id).await?;
  96. let comments = get_comments(rep)?;
  97. println!("Comments on Task with id {}:\n{}", id, comments);
  98. }
  99. Some(CliTauSubCommands::Get { id }) => {
  100. let task = get_by_id(rpc_addr, id).await?;
  101. let taskinfo: TaskInfo = serde_json::from_value(task.clone())?;
  102. let current_state: String = serde_json::from_value(get_state(rpc_addr, id).await?)?;
  103. let mut table = table!([Bd => "ref_id", &taskinfo.ref_id],
  104. ["id", &taskinfo.id.to_string()],
  105. [Bd =>"title", &taskinfo.title],
  106. ["desc", &taskinfo.desc],
  107. [Bd =>"assign", get_from_task(task.clone(), "assign")?],
  108. ["project", get_from_task(task.clone(), "project")?],
  109. [Bd =>"due", timestamp_to_date(task["due"].clone(),"date")],
  110. ["rank", &taskinfo.rank.to_string()],
  111. [Bd =>"created_at", timestamp_to_date(task["created_at"].clone(), "datetime")],
  112. ["current_state", &current_state],
  113. [Bd => "comments", get_comments(task.clone())?]);
  114. table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
  115. table.set_titles(row!["Name", "Value"]);
  116. table.printstd();
  117. let mut event_table = table!(["events", get_events(task.clone())?]);
  118. event_table.set_format(*format::consts::FORMAT_NO_COLSEP);
  119. event_table.printstd();
  120. }
  121. Some(CliTauSubCommands::List {}) | None => {
  122. let rep = list(rpc_addr, json!([])).await?;
  123. list_tasks(rep, vec![])?;
  124. }
  125. }
  126. }
  127. Ok(())
  128. }
  129. #[async_std::main]
  130. async fn main() -> Result<()> {
  131. let args = CliTau::parse();
  132. let matches = CliTau::command().get_matches();
  133. let verbosity_level = matches.occurrences_of("verbose");
  134. let (lvl, conf) = log_config(verbosity_level)?;
  135. TermLogger::init(lvl, conf, TerminalMode::Mixed, ColorChoice::Auto)?;
  136. let config_path = get_config_path(args.config.clone(), "taud_config.toml")?;
  137. spawn_config(&config_path, CONFIG_FILE_CONTENTS)?;
  138. let config: TauConfig = match Config::<TauConfig>::load(config_path) {
  139. Ok(c) => c,
  140. Err(_) => TauConfig::default(),
  141. };
  142. start(args, config).await
  143. }