diff --git a/src/flux/ui/cob.rs b/src/flux/ui/cob.rs index e23a0ca8..4a9baf1f 100644 --- a/src/flux/ui/cob.rs +++ b/src/flux/ui/cob.rs @@ -407,6 +407,8 @@ impl ToRow<8> for IssueItem { #[derive(Clone, Default, Debug, Eq, PartialEq)] pub struct IssueItemFilter { state: Option, + authored: bool, + authors: Vec, assigned: bool, assignees: Vec, search: Option, @@ -431,6 +433,20 @@ impl IssueItemFilter { None => true, }; + let matches_authored = if self.authored { + issue.author.you + } else { + true + }; + + let matches_authors = (!self.authors.is_empty()) + .then(|| { + self.authors + .iter() + .any(|other| issue.author.nid == Some(**other)) + }) + .unwrap_or(true); + let matches_assigned = self .assigned .then(|| issue.assignees.iter().any(|assignee| assignee.you)) @@ -457,7 +473,12 @@ impl IssueItemFilter { None => true, }; - matches_state && matches_assigned && matches_assignees && matches_search + matches_state + && matches_authored + && matches_authors + && matches_assigned + && matches_assignees + && matches_search } } @@ -467,9 +488,22 @@ impl FromStr for IssueItemFilter { fn from_str(value: &str) -> Result { let mut state = None; let mut search = String::new(); + let mut authored = false; + let mut authors = vec![]; let mut assigned = false; let mut assignees = vec![]; + let mut authors_parser = |input| -> IResult<&str, Vec<&str>> { + preceded( + tag("authors:"), + delimited( + tag("["), + separated_list0(tag(","), take(56_usize)), + tag("]"), + ), + )(input) + }; + let mut assignees_parser = |input| -> IResult<&str, Vec<&str>> { preceded( tag("assignees:"), @@ -495,20 +529,28 @@ impl FromStr for IssueItemFilter { reason: issue::CloseReason::Solved, }) } + "is:authored" => authored = true, "is:assigned" => assigned = true, - other => match assignees_parser.parse(other) { - Ok((_, dids)) => { + other => { + if let Ok((_, dids)) = assignees_parser.parse(other) { for did in dids { assignees.push(Did::from_str(did)?); } + } else if let Ok((_, dids)) = authors_parser.parse(other) { + for did in dids { + authors.push(Did::from_str(did)?); + } + } else { + search.push_str(other); } - _ => search.push_str(other), - }, + } } } Ok(Self { state, + authored, + authors, assigned, assignees, search: Some(search), @@ -800,11 +842,16 @@ mod tests { #[test] fn issue_item_filter_from_str_should_succeed() -> Result<()> { - let search = r#"is:open is:assigned assignees:[did:key:z6MkkpTPzcq1ybmjQyQpyre15JUeMvZY6toxoZVpLZ8YarsB,did:key:z6Mku8hpprWTmCv3BqkssCYDfr2feUdyLSUnycVajFo9XVAx] cli"#; + let search = r#"is:open is:assigned assignees:[did:key:z6MkkpTPzcq1ybmjQyQpyre15JUeMvZY6toxoZVpLZ8YarsB,did:key:z6Mku8hpprWTmCv3BqkssCYDfr2feUdyLSUnycVajFo9XVAx] is:authored authors:[did:key:z6Mku8hpprWTmCv3BqkssCYDfr2feUdyLSUnycVajFo9XVAx] cli"#; let actual = IssueItemFilter::from_str(search)?; let expected = IssueItemFilter { state: Some(issue::State::Open), + authors: vec![ + Did::from_str("did:key:z6MkkpTPzcq1ybmjQyQpyre15JUeMvZY6toxoZVpLZ8YarsB")?, + Did::from_str("did:key:z6Mku8hpprWTmCv3BqkssCYDfr2feUdyLSUnycVajFo9XVAx")?, + ], + authored: false, assigned: true, assignees: vec![ Did::from_str("did:key:z6MkkpTPzcq1ybmjQyQpyre15JUeMvZY6toxoZVpLZ8YarsB")?,