cli: Refactor `rad issue list`
Move code into its own method.
This commit is contained in:
parent
e0241050f8
commit
f4dff17085
|
|
@ -9,6 +9,7 @@ use radicle::cob::issue;
|
||||||
use radicle::cob::issue::{CloseReason, Issues, State};
|
use radicle::cob::issue::{CloseReason, Issues, State};
|
||||||
use radicle::node::Handle;
|
use radicle::node::Handle;
|
||||||
use radicle::prelude::Did;
|
use radicle::prelude::Did;
|
||||||
|
use radicle::profile;
|
||||||
use radicle::storage::WriteStorage;
|
use radicle::storage::WriteStorage;
|
||||||
use radicle::{cob, Node};
|
use radicle::{cob, Node};
|
||||||
use radicle_term::table::TableOptions;
|
use radicle_term::table::TableOptions;
|
||||||
|
|
@ -327,75 +328,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operation::List { assigned } => {
|
Operation::List { assigned } => {
|
||||||
if issues.is_empty()? {
|
list(&issues, &profile, &assigned)?;
|
||||||
term::print(term::format::italic("Nothing to show."));
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let assignee = match assigned {
|
|
||||||
Some(Assigned::Me) => Some(*profile.id()),
|
|
||||||
Some(Assigned::Peer(id)) => Some(id.into()),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut all = Vec::new();
|
|
||||||
for result in issues.all()? {
|
|
||||||
let (id, issue, _) = result?;
|
|
||||||
|
|
||||||
if Some(true) == assignee.map(|a| !issue.assigned().any(|v| v == Did::from(a))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
all.push((id, issue))
|
|
||||||
}
|
|
||||||
|
|
||||||
all.sort_by(|(id1, i1), (id2, i2)| {
|
|
||||||
let by_timestamp = i2.timestamp().cmp(&i1.timestamp());
|
|
||||||
let by_id = id1.cmp(id2);
|
|
||||||
|
|
||||||
by_timestamp.then(by_id)
|
|
||||||
});
|
|
||||||
|
|
||||||
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 (id, issue) in all {
|
|
||||||
let assigned: String = issue
|
|
||||||
.assigned()
|
|
||||||
.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([
|
|
||||||
match issue.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();
|
|
||||||
}
|
}
|
||||||
Operation::Delete { id } => {
|
Operation::Delete { id } => {
|
||||||
let id = id.resolve(&repo.backend)?;
|
let id = id.resolve(&repo.backend)?;
|
||||||
|
|
@ -416,6 +349,84 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn list(
|
||||||
|
issues: &Issues,
|
||||||
|
profile: &profile::Profile,
|
||||||
|
assigned: &Option<Assigned>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if issues.is_empty()? {
|
||||||
|
term::print(term::format::italic("Nothing to show."));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let assignee = match assigned {
|
||||||
|
Some(Assigned::Me) => Some(*profile.id()),
|
||||||
|
Some(Assigned::Peer(id)) => Some((*id).into()),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut all = Vec::new();
|
||||||
|
for result in issues.all()? {
|
||||||
|
let (id, issue, _) = result?;
|
||||||
|
|
||||||
|
if Some(true) == assignee.map(|a| !issue.assigned().any(|v| v == Did::from(a))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
all.push((id, issue))
|
||||||
|
}
|
||||||
|
|
||||||
|
all.sort_by(|(id1, i1), (id2, i2)| {
|
||||||
|
let by_timestamp = i2.timestamp().cmp(&i1.timestamp());
|
||||||
|
let by_id = id1.cmp(id2);
|
||||||
|
|
||||||
|
by_timestamp.then(by_id)
|
||||||
|
});
|
||||||
|
|
||||||
|
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 (id, issue) in all {
|
||||||
|
let assigned: String = issue
|
||||||
|
.assigned()
|
||||||
|
.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([
|
||||||
|
match issue.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();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn show_issue(issue: &issue::Issue) -> anyhow::Result<()> {
|
fn show_issue(issue: &issue::Issue) -> anyhow::Result<()> {
|
||||||
let tags: Vec<String> = issue.tags().cloned().map(|t| t.into()).collect();
|
let tags: Vec<String> = issue.tags().cloned().map(|t| t.into()).collect();
|
||||||
let assignees: Vec<String> = issue
|
let assignees: Vec<String> = issue
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue