ticket: use list state tokens in query
This commit is contained in:
parent
39be7a5a0a
commit
556adb429c
|
|
@ -510,6 +510,53 @@ impl NewTicket {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum TicketListState {
|
||||
Planning,
|
||||
Ready,
|
||||
Queued,
|
||||
InProgress,
|
||||
Done,
|
||||
Closed,
|
||||
}
|
||||
|
||||
impl TicketListState {
|
||||
pub fn parse(value: &str) -> Option<Self> {
|
||||
match value {
|
||||
"planning" => Some(Self::Planning),
|
||||
"ready" => Some(Self::Ready),
|
||||
"queued" => Some(Self::Queued),
|
||||
"inprogress" => Some(Self::InProgress),
|
||||
"done" => Some(Self::Done),
|
||||
"closed" => Some(Self::Closed),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Planning => "planning",
|
||||
Self::Ready => "ready",
|
||||
Self::Queued => "queued",
|
||||
Self::InProgress => "inprogress",
|
||||
Self::Done => "done",
|
||||
Self::Closed => "closed",
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_workflow_state(self, state: TicketWorkflowState) -> bool {
|
||||
match self {
|
||||
Self::Planning => state == TicketWorkflowState::Planning,
|
||||
Self::Ready => state == TicketWorkflowState::Ready,
|
||||
Self::Queued => state == TicketWorkflowState::Queued,
|
||||
Self::InProgress => state == TicketWorkflowState::InProgress,
|
||||
Self::Done => state == TicketWorkflowState::Done,
|
||||
Self::Closed => state == TicketWorkflowState::Closed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TicketStateSelector {
|
||||
|
|
@ -517,8 +564,8 @@ pub enum TicketStateSelector {
|
|||
Active,
|
||||
/// Every workflow state, including closed.
|
||||
All,
|
||||
/// An explicit set of workflow states.
|
||||
States(BTreeSet<TicketWorkflowState>),
|
||||
/// An explicit set of list-query state tokens.
|
||||
States(BTreeSet<TicketListState>),
|
||||
}
|
||||
|
||||
impl Default for TicketStateSelector {
|
||||
|
|
@ -551,11 +598,11 @@ impl TicketListQuery {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn state(state: TicketWorkflowState) -> Self {
|
||||
pub fn state(state: TicketListState) -> Self {
|
||||
Self::states([state])
|
||||
}
|
||||
|
||||
pub fn states(states: impl IntoIterator<Item = TicketWorkflowState>) -> Self {
|
||||
pub fn states(states: impl IntoIterator<Item = TicketListState>) -> Self {
|
||||
Self {
|
||||
state: TicketStateSelector::States(states.into_iter().collect()),
|
||||
}
|
||||
|
|
@ -565,7 +612,9 @@ impl TicketListQuery {
|
|||
match &self.state {
|
||||
TicketStateSelector::Active => state != TicketWorkflowState::Closed,
|
||||
TicketStateSelector::All => true,
|
||||
TicketStateSelector::States(states) => states.contains(&state),
|
||||
TicketStateSelector::States(states) => states
|
||||
.iter()
|
||||
.any(|query_state| query_state.matches_workflow_state(state)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4060,15 +4109,15 @@ state: planning
|
|||
assert!(all_ids.contains(&closed.id.as_str()));
|
||||
|
||||
let ready_only = backend
|
||||
.list(TicketListQuery::state(TicketWorkflowState::Ready))
|
||||
.list(TicketListQuery::state(TicketListState::Ready))
|
||||
.unwrap();
|
||||
assert_eq!(ready_only.len(), 1);
|
||||
assert_eq!(ready_only[0].id, ready.id);
|
||||
|
||||
let planning_or_closed = backend
|
||||
.list(TicketListQuery::states([
|
||||
TicketWorkflowState::Planning,
|
||||
TicketWorkflowState::Closed,
|
||||
TicketListState::Planning,
|
||||
TicketListState::Closed,
|
||||
]))
|
||||
.unwrap();
|
||||
let explicit_ids = planning_or_closed
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ use crate::{
|
|||
NewTicket, NewTicketEvent, NewTicketRelation, OrchestrationPlanKind, OrchestrationPlanRecord,
|
||||
Result as TicketResult, Ticket, TicketBackend, TicketDoctorDiagnostic, TicketDoctorReport,
|
||||
TicketDoctorSeverity, TicketError, TicketEventKind, TicketIdOrSlug, TicketIntakeSummary,
|
||||
TicketRef, TicketRelation, TicketRelationKind, TicketRelationView, TicketReview,
|
||||
TicketReviewResult, TicketStateChange, TicketSummary, TicketWorkflowState,
|
||||
TicketListState, TicketRef, TicketRelation, TicketRelationKind, TicketRelationView,
|
||||
TicketReview, TicketReviewResult, TicketStateChange, TicketSummary, TicketWorkflowState,
|
||||
};
|
||||
|
||||
const DEFAULT_LIST_LIMIT: usize = 50;
|
||||
|
|
@ -373,6 +373,17 @@ impl TicketWorkflowStateParam {
|
|||
Self::Closed => TicketWorkflowState::Closed,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_list_state(self) -> TicketListState {
|
||||
match self {
|
||||
Self::Planning => TicketListState::Planning,
|
||||
Self::Ready => TicketListState::Ready,
|
||||
Self::Queued => TicketListState::Queued,
|
||||
Self::Inprogress => TicketListState::InProgress,
|
||||
Self::Done => TicketListState::Done,
|
||||
Self::Closed => TicketListState::Closed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, schemars::JsonSchema)]
|
||||
|
|
@ -389,14 +400,14 @@ enum TicketListStateParam {
|
|||
}
|
||||
|
||||
impl TicketListStateParam {
|
||||
fn as_state(self) -> Option<TicketWorkflowState> {
|
||||
fn as_list_state(self) -> Option<TicketListState> {
|
||||
match self {
|
||||
Self::Planning => Some(TicketWorkflowState::Planning),
|
||||
Self::Ready => Some(TicketWorkflowState::Ready),
|
||||
Self::Queued => Some(TicketWorkflowState::Queued),
|
||||
Self::Inprogress => Some(TicketWorkflowState::InProgress),
|
||||
Self::Done => Some(TicketWorkflowState::Done),
|
||||
Self::Closed => Some(TicketWorkflowState::Closed),
|
||||
Self::Planning => Some(TicketListState::Planning),
|
||||
Self::Ready => Some(TicketListState::Ready),
|
||||
Self::Queued => Some(TicketListState::Queued),
|
||||
Self::Inprogress => Some(TicketListState::InProgress),
|
||||
Self::Done => Some(TicketListState::Done),
|
||||
Self::Closed => Some(TicketListState::Closed),
|
||||
Self::Active | Self::All => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -428,15 +439,15 @@ impl TicketListParams {
|
|||
"TicketList `states` must include at least one workflow state".to_string(),
|
||||
));
|
||||
}
|
||||
crate::TicketListQuery::states(states.into_iter().map(|state| state.into_state()))
|
||||
crate::TicketListQuery::states(states.into_iter().map(|state| state.into_list_state()))
|
||||
} else {
|
||||
match self.state.unwrap_or(TicketListStateParam::Active) {
|
||||
TicketListStateParam::Active => crate::TicketListQuery::active(),
|
||||
TicketListStateParam::All => crate::TicketListQuery::all(),
|
||||
state => crate::TicketListQuery::state(
|
||||
state
|
||||
.as_state()
|
||||
.expect("workflow state list param maps to TicketWorkflowState"),
|
||||
.as_list_state()
|
||||
.expect("workflow state list param maps to TicketListState"),
|
||||
),
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ use ticket::config::{
|
|||
use ticket::{
|
||||
LocalTicketBackend, MarkdownText, NewTicket, NewTicketEvent, NewTicketRelation, TicketBackend,
|
||||
TicketDoctorSeverity, TicketEventKind, TicketIdOrSlug, TicketIntakeSummary, TicketListQuery,
|
||||
TicketRelationKind, TicketReview, TicketReviewResult, TicketSummary, TicketWorkflowState,
|
||||
TicketListState, TicketRelationKind, TicketReview, TicketReviewResult, TicketSummary,
|
||||
TicketWorkflowState,
|
||||
};
|
||||
|
||||
const DEFAULT_LIST_LIMIT: usize = 50;
|
||||
|
|
@ -49,7 +50,7 @@ pub struct CreateOptions {
|
|||
pub enum ListState {
|
||||
Active,
|
||||
All,
|
||||
States(Vec<TicketWorkflowState>),
|
||||
States(Vec<TicketListState>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
|
@ -1060,7 +1061,7 @@ fn parse_list_state(raw: &str) -> Result<ListState, TicketCliError> {
|
|||
|
||||
let mut states = Vec::new();
|
||||
for token in tokens {
|
||||
let state = TicketWorkflowState::parse(token).ok_or_else(|| {
|
||||
let state = TicketListState::parse(token).ok_or_else(|| {
|
||||
TicketCliError::new(format!(
|
||||
"invalid state: {token}; expected active, all, planning, ready, queued, inprogress, done, closed"
|
||||
))
|
||||
|
|
@ -1554,18 +1555,17 @@ mod tests {
|
|||
fn ticket_cli_list_defaults_to_active_and_accepts_multi_state_filter() {
|
||||
let default = parse_ticket_args(&args(&["list"])).unwrap();
|
||||
match default {
|
||||
TicketCommand::List(options) => assert_eq!(options.state, ListState::Active),
|
||||
TicketCli::Command(TicketCommand::List(options)) => {
|
||||
assert_eq!(options.state, ListState::Active)
|
||||
}
|
||||
other => panic!("unexpected command: {other:?}"),
|
||||
}
|
||||
|
||||
let explicit = parse_ticket_args(&args(&["list", "--state", "planning,closed"])).unwrap();
|
||||
match explicit {
|
||||
TicketCommand::List(options) => assert_eq!(
|
||||
TicketCli::Command(TicketCommand::List(options)) => assert_eq!(
|
||||
options.state,
|
||||
ListState::States(vec![
|
||||
TicketWorkflowState::Planning,
|
||||
TicketWorkflowState::Closed
|
||||
])
|
||||
ListState::States(vec![TicketListState::Planning, TicketListState::Closed])
|
||||
),
|
||||
other => panic!("unexpected command: {other:?}"),
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user