From efdfe7b530b39e220c169ffce673d0e33b706b3b Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Tue, 30 Jan 2024 10:58:45 +0100 Subject: [PATCH] issue-select: Add filter arguments --- bin/commands/issue.rs | 22 ++++++++++++++- src/cob/issue.rs | 62 ++++++++++++++++++++++++++----------------- 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/bin/commands/issue.rs b/bin/commands/issue.rs index 038d0597..4bf69a61 100644 --- a/bin/commands/issue.rs +++ b/bin/commands/issue.rs @@ -11,7 +11,7 @@ use anyhow::anyhow; use radicle_tui as tui; -use tui::cob::issue::{self}; +use tui::cob::issue::{self, State}; use tui::{context, log, Window}; use crate::terminal; @@ -89,6 +89,26 @@ impl Args for Options { unknown => anyhow::bail!("unknown mode '{}'", unknown), }; } + Long("all") if op == Some(OperationName::Select) => { + select_opts.filter = select_opts.filter.with_state(None); + } + Long("open") if op == Some(OperationName::Select) => { + select_opts.filter = select_opts.filter.with_state(Some(State::Open)); + } + Long("solved") if op == Some(OperationName::Select) => { + select_opts.filter = select_opts.filter.with_state(Some(State::Solved)); + } + Long("closed") if op == Some(OperationName::Select) => { + select_opts.filter = select_opts.filter.with_state(Some(State::Closed)); + } + Long("assigned") if op == Some(OperationName::Select) => { + if let Ok(val) = parser.value() { + select_opts.filter = + select_opts.filter.with_assginee(terminal::args::did(&val)?); + } else { + select_opts.filter = select_opts.filter.with_assgined(true); + } + } Value(val) if op.is_none() => match val.to_string_lossy().as_ref() { "select" => op = Some(OperationName::Select), diff --git a/src/cob/issue.rs b/src/cob/issue.rs index edac1d2f..cb2c7baa 100644 --- a/src/cob/issue.rs +++ b/src/cob/issue.rs @@ -3,6 +3,7 @@ use std::fmt::Display; use anyhow::Result; use radicle::cob::issue::{Issue, IssueId, Issues}; use radicle::cob::Label; +use radicle::issue::CloseReason; use radicle::prelude::{Did, Signer}; use radicle::storage::git::Repository; use radicle::{issue, Profile}; @@ -13,6 +14,7 @@ use super::format; pub enum State { #[default] Open, + Solved, Closed, } @@ -20,6 +22,7 @@ impl Display for State { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let state = match self { State::Open => "open", + State::Solved => "solved", State::Closed => "closed", }; f.write_str(state) @@ -29,8 +32,8 @@ impl Display for State { #[derive(Clone, Default, Debug, Eq, PartialEq)] pub struct Filter { state: Option, - authored: bool, - authors: Vec, + assigned: bool, + assignees: Vec, } impl Filter { @@ -39,37 +42,48 @@ impl Filter { self } - pub fn with_authored(mut self, authored: bool) -> Self { - self.authored = authored; + pub fn with_assgined(mut self, assigned: bool) -> Self { + self.assigned = assigned; self } - pub fn with_author(mut self, author: Did) -> Self { - self.authors.push(author); + pub fn with_assginee(mut self, assignee: Did) -> Self { + self.assignees.push(assignee); self } pub fn matches(&self, profile: &Profile, issue: &Issue) -> bool { let matches_state = match self.state { Some(State::Open) => matches!(issue.state(), issue::State::Open), + Some(State::Solved) => matches!( + issue.state(), + issue::State::Closed { + reason: CloseReason::Solved + } + ), Some(State::Closed) => matches!(issue.state(), issue::State::Closed { .. }), None => true, }; - let matches_authored = self - .authored - .then(|| *issue.author().id() == profile.did()) - .unwrap_or(true); - - let matches_authors = (!self.authors.is_empty()) + let matches_assgined = self + .assigned .then(|| { - self.authors - .iter() - .any(|other| *issue.author().id() == *other) + issue + .assignees() + .collect::>() + .contains(&&profile.did()) }) .unwrap_or(true); - matches_state && matches_authored && matches_authors + let matches_assignees = (!self.assignees.is_empty()) + .then(|| { + self.assignees + .iter() + .any(|other| issue.assignees().collect::>().contains(&other)) + }) + .unwrap_or(true); + + matches_state && matches_assgined && matches_assignees } } @@ -82,19 +96,19 @@ impl ToString for Filter { filter.push_str(&format!("is:{}", state)); filter.push(' '); } - if self.authored { - filter.push_str("is:authored"); + if self.assigned { + filter.push_str("is:assgined"); filter.push(' '); } - if !self.authors.is_empty() { - filter.push_str("authors:"); + if !self.assignees.is_empty() { + filter.push_str("assignees:"); filter.push('['); - let mut authors = self.authors.iter().peekable(); - while let Some(author) = authors.next() { - filter.push_str(&format::did(author)); + let mut assignees = self.assignees.iter().peekable(); + while let Some(assignee) = assignees.next() { + filter.push_str(&format::did(assignee)); - if authors.peek().is_some() { + if assignees.peek().is_some() { filter.push(','); } }