From 90ae6068b2cc2256e9d6dce1e88124e92394254f Mon Sep 17 00:00:00 2001 From: Michael Gattozzi Date: Mon, 23 Dec 2019 19:36:16 -0500 Subject: Add the ability to assign users to tickets --- ticket/src/main.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++--- ticket/src/tui.rs | 22 ++++++++++++++-- 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/ticket/src/main.rs b/ticket/src/main.rs index 88e86cd..652bd01 100644 --- a/ticket/src/main.rs +++ b/ticket/src/main.rs @@ -52,6 +52,23 @@ enum Cmd { Close { id: Uuid }, /// Comment on a ticket from the command line Comment { id: Uuid, message: String }, + /// Assing someone to a ticket from the command line + Assign { + id: Uuid, + #[structopt(subcommand)] + to: Placeholder, + }, +} + +#[derive(structopt::StructOpt)] +enum Placeholder { + To(Who), +} + +#[derive(structopt::StructOpt)] +enum Who { + Me, + Them { id: Uuid, name: String }, } #[paw::main] @@ -69,6 +86,7 @@ fn main(args: Args) { Cmd::Show { id } => show(id), Cmd::Close { id } => close(id), Cmd::Comment { id, message } => comment(id, message), + Cmd::Assign { id, to } => assign(id, to), } { error!("{}", e); std::process::exit(1); @@ -135,7 +153,9 @@ fn new() -> Result<()> { version: Version::V1, }; - save_ticket(&t) + save_ticket(&t)?; + println!("Ticket Created: {}", t.id); + Ok(()) } fn show(id: Uuid) -> Result<()> { @@ -154,7 +174,19 @@ fn show(id: Uuid) -> Result<()> { if ticket.assignees.is_empty() { "None".to_owned().blue() } else { - ticket.assignees.join(", ").blue() + let mut commas = ticket.assignees.len(); + ticket + .assignees + .into_iter() + .fold(String::new(), |mut acc, (_, name)| { + acc.push_str(&name.0); + if commas > 1 { + acc.push_str(", "); + commas -= 1; + } + acc + }) + .blue() }, ticket.description, ticket.comments.values().fold( @@ -205,7 +237,7 @@ fn migrate() -> Result<()> { title: t.title, status: t.status, id: uuid_v1()?, - assignees: t.assignee.map_or_else(Vec::new, |a| vec![a]), + assignees: Vec::new(), description: t.description, comments: BTreeMap::new(), version: Version::V1, @@ -240,6 +272,41 @@ fn comment(id: Uuid, message: String) -> Result<()> { save_ticket(&ticket)?; Ok(()) } + +fn assign(id: Uuid, to: Placeholder) -> Result<()> { + let mut ticket = get_all_tickets()? + .into_iter() + .find(|t| t.id == id) + .ok_or_else(|| { + format_err!("The uuid '{}' is not associated with any ticket") + })?; + match to { + Placeholder::To(who) => match who { + Who::Me => { + let config = get_user_config()?; + if !ticket + .assignees + .iter() + .any(|(id, name)| config.uuid == *id && config.name == name.0) + { + ticket.assignees.push((config.uuid, Name(config.name))); + } + save_ticket(&ticket)?; + } + Who::Them { id, name } => { + let assignee_does_not_exist = + !ticket.assignees.iter().any(|(id_inside, name_inside)| { + id == *id_inside && name == name_inside.0 + }); + if assignee_does_not_exist { + ticket.assignees.push((id, Name(name))); + } + save_ticket(&ticket)?; + } + }, + } + Ok(()) +} #[derive(Serialize, Deserialize, Debug)] /// The fundamental type this tool revolves around. The ticket represents /// everything about an issue or future plan for the code base. @@ -247,7 +314,7 @@ pub struct Ticket { title: String, status: Status, id: Uuid, - assignees: Vec, + assignees: Vec<(Uuid, Name)>, description: String, version: Version, #[serde(serialize_with = "toml::ser::tables_last")] diff --git a/ticket/src/tui.rs b/ticket/src/tui.rs index a4fdd35..015ecc9 100644 --- a/ticket/src/tui.rs +++ b/ticket/src/tui.rs @@ -369,13 +369,31 @@ impl<'a> App<'a> { ]; let name_style = Style::default().fg(Color::Cyan).modifier(Modifier::BOLD); + if i.0.assignees.is_empty() { + desc.push(Text::styled("\nAssignees\n---------\n", header)); + } else { + desc.push(Text::styled("\nAssignees\n---------\n", header)); + if i.0.assignees.len() == 1 { + let (_, name) = &i.0.assignees[0]; + desc.push(Text::styled(name.0.clone(), name_style)); + } else { + for (idx, (_, name)) in i.0.assignees.iter().enumerate() { + if idx < i.0.assignees.len() - 1 { + desc.push(Text::styled(format!("{}, ", name.0), name_style)); + } else { + desc.push(Text::styled(name.0.clone(), name_style)); + } + } + } + } + if i.0.comments.is_empty() { desc.push(Text::styled("\nComments\n--------\n", header)); } else { desc.push(Text::styled("\nComments\n--------\n", header)); for (_, name, comment) in i.0.comments.values() { - desc.push(Text::styled(format!("\n{}\n", name.0), name_style)); - desc.push(Text::raw(format!("{}\n", comment.0))); + desc.push(Text::styled(format!("{}\n", name.0), name_style)); + desc.push(Text::raw(format!("{}\n\n", comment.0))); } } desc -- cgit v1.2.3