cli: Render `rad issue list` with a nice table
This commit is contained in:
parent
2ff5ad97f3
commit
ff56843fcc
|
|
@ -17,7 +17,11 @@ The issue is now listed under our project.
|
|||
|
||||
```
|
||||
$ rad issue list
|
||||
2e8c1bf3fe0532a314778357c886608a966a34bd "flux capacitor underpowered" ❲unassigned❳
|
||||
╭───────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ● ID Title Author Tags Assignees Opened │
|
||||
├───────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● 2e8c1bf flux capacitor underpowered z6MknSL…StBU8Vi [ .. ] │
|
||||
╰───────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Show the issue information issue.
|
||||
|
|
@ -48,7 +52,11 @@ It will now show in the list of issues assigned to us.
|
|||
|
||||
```
|
||||
$ rad issue list --assigned
|
||||
2e8c1bf3fe0532a314778357c886608a966a34bd "flux capacitor underpowered" did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ● ID Title Author Tags Assignees Opened │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● 2e8c1bf flux capacitor underpowered z6MknSL…StBU8Vi z6MknSL…StBU8Vi [ .. ] │
|
||||
╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Note: this can always be undone with the `unassign` subcommand.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,11 @@ The issue is now listed under our project.
|
|||
|
||||
```
|
||||
$ rad issue list
|
||||
b05e945bb63c11bf80320f4e26ad1d1f7c51f755 "flux capacitor underpowered" ❲unassigned❳
|
||||
╭───────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ● ID Title Author Tags Assignees Opened │
|
||||
├───────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● b05e945 flux capacitor underpowered z6Mkt67…v4N1tRk [ .. ] │
|
||||
╰───────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Great! Now we've documented the issue for ourselves and others.
|
||||
|
|
@ -35,7 +39,11 @@ It will now show in the list of issues assigned to us.
|
|||
|
||||
```
|
||||
$ rad issue list --assigned
|
||||
b05e945bb63c11bf80320f4e26ad1d1f7c51f755 "flux capacitor underpowered" did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ● ID Title Author Tags Assignees Opened │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● b05e945 flux capacitor underpowered z6Mkt67…v4N1tRk z6Mkt67…v4N1tRk [ .. ] │
|
||||
╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Note: this can always be undone with the `unassign` subcommand.
|
||||
|
|
|
|||
|
|
@ -314,10 +314,22 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
None => None,
|
||||
};
|
||||
|
||||
let mut t = term::Table::new(term::table::TableOptions::default());
|
||||
let mut t = term::Table::new(term::table::TableOptions::bordered());
|
||||
t.push([
|
||||
term::format::dim(String::from("●")),
|
||||
term::format::bold(String::from("ID")),
|
||||
term::format::bold(String::from("Title")),
|
||||
term::format::bold(String::from("Author")),
|
||||
term::format::bold(String::from("Tags")),
|
||||
term::format::bold(String::from("Assignees")),
|
||||
term::format::bold(String::from("Opened")),
|
||||
]);
|
||||
t.divider();
|
||||
|
||||
for result in issues.all()? {
|
||||
let (id, issue, _) = result?;
|
||||
let assigned: Vec<_> = issue.assigned().collect();
|
||||
let state = issue.state();
|
||||
|
||||
if Some(true) == assignee.map(|a| !assigned.contains(&Did::from(a))) {
|
||||
continue;
|
||||
|
|
@ -325,17 +337,28 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
|
||||
let assigned: String = assigned
|
||||
.iter()
|
||||
.map(|p| p.to_string())
|
||||
.map(|p| term::format::did(p).to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
let mut tags = issue.tags().map(|t| t.to_string()).collect::<Vec<_>>();
|
||||
tags.sort();
|
||||
|
||||
t.push([
|
||||
id.to_string(),
|
||||
format!("{:?}", issue.title()),
|
||||
if assigned.is_empty() {
|
||||
String::from("❲unassigned❳")
|
||||
} else {
|
||||
assigned.to_string()
|
||||
match state {
|
||||
State::Open => term::format::positive("●").into(),
|
||||
State::Closed { .. } => term::format::negative("●").into(),
|
||||
},
|
||||
term::format::tertiary(term::format::cob(&id)).to_owned(),
|
||||
term::format::default(issue.title().to_owned()),
|
||||
term::format::did(&issue.author().id).dim(),
|
||||
term::format::secondary(tags.join(", ")),
|
||||
if assigned.is_empty() {
|
||||
term::format::dim(String::default())
|
||||
} else {
|
||||
term::format::default(assigned.to_string())
|
||||
},
|
||||
term::format::timestamp(&issue.timestamp()).dim().italic(),
|
||||
]);
|
||||
}
|
||||
t.print();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ pub use radicle_term::{style, Paint};
|
|||
|
||||
use radicle::cob::{ObjectId, Timestamp};
|
||||
use radicle::node::NodeId;
|
||||
use radicle::prelude::Did;
|
||||
use radicle::profile::Profile;
|
||||
|
||||
use crate::terminal as term;
|
||||
|
|
@ -33,13 +34,19 @@ pub fn cob(id: &ObjectId) -> String {
|
|||
format!("{:.7}", id.to_string())
|
||||
}
|
||||
|
||||
/// Format a DID.
|
||||
pub fn did(did: &Did) -> Paint<String> {
|
||||
let nid = did.as_key().to_human();
|
||||
Paint::new(format!("{}…{}", &nid[..7], &nid[nid.len() - 7..]))
|
||||
}
|
||||
|
||||
/// Format a timestamp.
|
||||
pub fn timestamp(time: &Timestamp) -> String {
|
||||
pub fn timestamp(time: &Timestamp) -> Paint<String> {
|
||||
let fmt = timeago::Formatter::new();
|
||||
let now = Timestamp::now();
|
||||
let duration = time::Duration::from_secs(now.as_secs() - time.as_secs());
|
||||
|
||||
fmt.convert(duration)
|
||||
Paint::new(fmt.convert(duration))
|
||||
}
|
||||
|
||||
/// Identity formatter that takes a profile and displays it as
|
||||
|
|
|
|||
|
|
@ -257,7 +257,6 @@ fn rad_node() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn rad_patch() {
|
||||
let mut environment = Environment::new();
|
||||
let profile = environment.profile("alice");
|
||||
|
|
@ -641,7 +640,6 @@ fn test_replication_via_seed() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn rad_workflow() {
|
||||
let mut environment = Environment::new();
|
||||
let alice = environment.node("alice");
|
||||
|
|
|
|||
|
|
@ -350,9 +350,7 @@ impl PublicKey {
|
|||
|
||||
/// Encode public key in human-readable format.
|
||||
///
|
||||
/// We use the format specified by the DID `key` method, which is described as:
|
||||
///
|
||||
/// `did:key:MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes))`
|
||||
/// `MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes))`
|
||||
///
|
||||
pub fn to_human(&self) -> String {
|
||||
let mut buf = [0; 2 + ed25519::PublicKey::BYTES];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::fmt;
|
||||
use std::fmt::{self, Display};
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -139,6 +139,12 @@ impl FromStr for Tag {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for Tag {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Tag> for String {
|
||||
fn from(Tag(name): Tag) -> Self {
|
||||
name
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ pub enum DidError {
|
|||
pub struct Did(crypto::PublicKey);
|
||||
|
||||
impl Did {
|
||||
/// We use the format specified by the DID `key` method, which is described as:
|
||||
///
|
||||
/// `did:key:MULTIBASE(base58-btc, MULTICODEC(public-key-type, raw-public-key-bytes))`
|
||||
///
|
||||
pub fn encode(&self) -> String {
|
||||
format!("did:key:{}", self.0.to_human())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue