Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
issue-select: Add filter arguments
Erik Kundt committed 2 years ago
commit efdfe7b530b39e220c169ffce673d0e33b706b3b
parent 26fae956fa15b7cb35d331253378fb16b54f03e0
2 files changed +56 -22
modified 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),
modified 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<State>,
-
    authored: bool,
-
    authors: Vec<Did>,
+
    assigned: bool,
+
    assignees: Vec<Did>,
}

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())
+
        let matches_assgined = self
+
            .assigned
+
            .then(|| {
+
                issue
+
                    .assignees()
+
                    .collect::<Vec<_>>()
+
                    .contains(&&profile.did())
+
            })
            .unwrap_or(true);

-
        let matches_authors = (!self.authors.is_empty())
+
        let matches_assignees = (!self.assignees.is_empty())
            .then(|| {
-
                self.authors
+
                self.assignees
                    .iter()
-
                    .any(|other| *issue.author().id() == *other)
+
                    .any(|other| issue.assignees().collect::<Vec<_>>().contains(&other))
            })
            .unwrap_or(true);

-
        matches_state && matches_authored && matches_authors
+
        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(',');
                }
            }