diff --git a/radicle-cli/examples/rad-issue.md b/radicle-cli/examples/rad-issue.md index 46ec426b..952364f3 100644 --- a/radicle-cli/examples/rad-issue.md +++ b/radicle-cli/examples/rad-issue.md @@ -5,12 +5,12 @@ Let's say the new car you are designing with your peers has a problem with its f ``` $ rad issue open --title "flux capacitor underpowered" --description "Flux capacitor power requirements exceed current supply" --no-announce -title: flux capacitor underpowered -state: open -tags: [] -assignees: [] - -Flux capacitor power requirements exceed current supply +╭─────────────────────────────────────────────────────────╮ +│ Title flux capacitor underpowered │ +│ Status open │ +│ │ +│ Flux capacitor power requirements exceed current supply │ +╰─────────────────────────────────────────────────────────╯ ``` The issue is now listed under our project. @@ -28,12 +28,12 @@ Show the issue information issue. ``` $ rad issue show 2e8c1bf -title: flux capacitor underpowered -state: open -tags: [] -assignees: [] - -Flux capacitor power requirements exceed current supply +╭─────────────────────────────────────────────────────────╮ +│ Title flux capacitor underpowered │ +│ Status open │ +│ │ +│ Flux capacitor power requirements exceed current supply │ +╰─────────────────────────────────────────────────────────╯ ``` diff --git a/radicle-cli/examples/rad-tag.md b/radicle-cli/examples/rad-tag.md index 8e1aa2f4..453c6062 100644 --- a/radicle-cli/examples/rad-tag.md +++ b/radicle-cli/examples/rad-tag.md @@ -9,12 +9,13 @@ We can now show the issue to check whether those tags were added: ``` $ rad issue show 2e8c1bf3fe0532a314778357c886608a966a34bd -title: flux capacitor underpowered -state: open -tags: [bug, good-first-issue] -assignees: [] - -Flux capacitor power requirements exceed current supply +╭─────────────────────────────────────────────────────────╮ +│ Title flux capacitor underpowered │ +│ Tags bug, good-first-issue │ +│ Status open │ +│ │ +│ Flux capacitor power requirements exceed current supply │ +╰─────────────────────────────────────────────────────────╯ ``` Untagging an issue is very similar: @@ -27,10 +28,11 @@ Notice that the `good-first-issue` tag has disappeared: ``` $ rad issue show 2e8c1bf3fe0532a314778357c886608a966a34bd -title: flux capacitor underpowered -state: open -tags: [bug] -assignees: [] - -Flux capacitor power requirements exceed current supply +╭─────────────────────────────────────────────────────────╮ +│ Title flux capacitor underpowered │ +│ Tags bug │ +│ Status open │ +│ │ +│ Flux capacitor power requirements exceed current supply │ +╰─────────────────────────────────────────────────────────╯ ``` diff --git a/radicle-cli/examples/workflow/3-issues.md b/radicle-cli/examples/workflow/3-issues.md index 45692260..d60be38b 100644 --- a/radicle-cli/examples/workflow/3-issues.md +++ b/radicle-cli/examples/workflow/3-issues.md @@ -5,12 +5,12 @@ Let's say the new car you are designing with your peers has a problem with its f ``` $ rad issue open --title "flux capacitor underpowered" --description "Flux capacitor power requirements exceed current supply" --no-announce -title: flux capacitor underpowered -state: open -tags: [] -assignees: [] - -Flux capacitor power requirements exceed current supply +╭─────────────────────────────────────────────────────────╮ +│ Title flux capacitor underpowered │ +│ Status open │ +│ │ +│ Flux capacitor power requirements exceed current supply │ +╰─────────────────────────────────────────────────────────╯ ``` The issue is now listed under our project. @@ -46,6 +46,19 @@ $ rad issue list --assigned ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ``` +In addition, you can see that when you run `rad issue show` you are listed under the `Assignees`. + +``` +$ rad issue show b05e945 +╭─────────────────────────────────────────────────────────╮ +│ Title flux capacitor underpowered │ +│ Assignees z6Mkt67…v4N1tRk │ +│ Status open │ +│ │ +│ Flux capacitor power requirements exceed current supply │ +╰─────────────────────────────────────────────────────────╯ +``` + Note: this can always be undone with the `unassign` subcommand. Great, now we have communicated to the world about our car's defect. diff --git a/radicle-cli/src/commands/issue.rs b/radicle-cli/src/commands/issue.rs index 3ad39c42..2dc3d37c 100644 --- a/radicle-cli/src/commands/issue.rs +++ b/radicle-cli/src/commands/issue.rs @@ -11,6 +11,8 @@ use radicle::node::Handle; use radicle::prelude::Did; use radicle::storage::WriteStorage; use radicle::{cob, Node}; +use radicle_term::table::TableOptions; +use radicle_term::{Paint, Table, VStack}; use crate::git::Rev; use crate::terminal as term; @@ -406,14 +408,58 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { fn show_issue(issue: &issue::Issue) -> anyhow::Result<()> { let tags: Vec = issue.tags().cloned().map(|t| t.into()).collect(); - let assignees: Vec = issue.assigned().map(|a| a.to_string()).collect(); + let assignees: Vec = issue.assigned().map(|a| term::format::did(&a).to_string()).collect(); - term::info!("title: {}", issue.title()); - term::info!("state: {}", issue.state()); - term::info!("tags: [{}]", tags.join(", ")); - term::info!("assignees: [{}]", assignees.join(", ")); - term::blank(); - term::info!("{}", issue.description().unwrap_or_default()); + let mut attrs = Table::<2, Paint>::new(TableOptions { + spacing: 2, + ..TableOptions::default() + }); + + attrs.push([ + term::format::tertiary("Title".to_owned()), + term::format::bold(issue.title().to_owned()), + ]); + + if !tags.is_empty() { + attrs.push([ + term::format::tertiary("Tags".to_owned()), + term::format::secondary(tags.join(", ")), + ]); + } + + if !assignees.is_empty() { + attrs.push([ + term::format::tertiary("Assignees".to_owned()), + term::format::dim(assignees.join(", ")), + ]); + } + + attrs.push([ + term::format::tertiary("Status".to_owned()), + match issue.state() { + issue::State::Open => term::format::positive("open".to_owned()), + issue::State::Closed { reason } => term::format::default(format!( + "{} {}", + term::format::negative("closed"), + term::format::default(format!("as {reason}")) + )), + }, + ]); + + let description = issue.description().unwrap_or_default(); + let widget = VStack::default() + .border(Some(term::colors::FAINT)) + .child(attrs) + .children(if !description.is_empty() { + vec![ + term::Label::blank().boxed(), + term::textarea(term::format::dim(description)).boxed(), + ] + } else { + vec![] + }); + + widget.print(); Ok(()) } diff --git a/radicle/src/cob/issue.rs b/radicle/src/cob/issue.rs index 6d0d31a8..acafcfc3 100644 --- a/radicle/src/cob/issue.rs +++ b/radicle/src/cob/issue.rs @@ -48,6 +48,16 @@ pub enum CloseReason { Solved, } +impl std::fmt::Display for CloseReason { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let reason = match self { + Self::Other => "unspecified", + Self::Solved => "solved", + }; + write!(f, "{reason}") + } +} + /// Issue state. #[derive(Debug, Default, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "status")]