httpd: Add cob state to listing endpoints
This commit adds the cob state of either patches or issues to the corresponding endpoint. So we can either query a cob listing with the required state or expect the default state. And once filtered by cob state we paginate. Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
This commit is contained in:
parent
6f17a4db67
commit
8667553740
|
|
@ -14,8 +14,8 @@ use serde_json::json;
|
|||
use tokio::sync::RwLock;
|
||||
use tower_http::cors::{self, CorsLayer};
|
||||
|
||||
use radicle::cob::issue::Issues;
|
||||
use radicle::cob::patch::Patches;
|
||||
use radicle::cob::issue;
|
||||
use radicle::cob::patch;
|
||||
use radicle::identity::Id;
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
use radicle::Profile;
|
||||
|
|
@ -50,8 +50,8 @@ impl Context {
|
|||
let doc = repo.identity_doc()?.1.verified()?;
|
||||
let payload = doc.project()?;
|
||||
let delegates = doc.delegates;
|
||||
let issues = Issues::open(&repo)?.counts()?;
|
||||
let patches = Patches::open(&repo)?.counts()?;
|
||||
let issues = issue::Issues::open(&repo)?.counts()?;
|
||||
let patches = patch::Patches::open(&repo)?.counts()?;
|
||||
|
||||
Ok(project::Info {
|
||||
payload,
|
||||
|
|
@ -115,6 +115,52 @@ pub struct PaginationQuery {
|
|||
pub per_page: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CobsQuery<T> {
|
||||
pub page: Option<usize>,
|
||||
pub per_page: Option<usize>,
|
||||
pub state: Option<T>,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum IssueState {
|
||||
Closed,
|
||||
#[default]
|
||||
Open,
|
||||
}
|
||||
|
||||
impl IssueState {
|
||||
pub fn matches(&self, issue: &issue::State) -> bool {
|
||||
match self {
|
||||
Self::Open => matches!(issue, issue::State::Open),
|
||||
Self::Closed => matches!(issue, issue::State::Closed { .. }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum PatchState {
|
||||
#[default]
|
||||
Open,
|
||||
Draft,
|
||||
Archived,
|
||||
Merged,
|
||||
}
|
||||
|
||||
impl PatchState {
|
||||
pub fn matches(&self, patch: &patch::State) -> bool {
|
||||
match self {
|
||||
Self::Open => matches!(patch, patch::State::Open),
|
||||
Self::Draft => matches!(patch, patch::State::Draft),
|
||||
Self::Archived => matches!(patch, patch::State::Archived),
|
||||
Self::Merged => matches!(patch, patch::State::Merged),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod project {
|
||||
use nonempty::NonEmpty;
|
||||
use serde::Serialize;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use radicle_surf::{Glob, Oid, Repository};
|
|||
|
||||
use crate::api::error::Error;
|
||||
use crate::api::project::Info;
|
||||
use crate::api::{self, Context, PaginationQuery};
|
||||
use crate::api::{self, CobsQuery, Context, PaginationQuery};
|
||||
use crate::axum_extra::{Path, Query};
|
||||
|
||||
const CACHE_1_HOUR: &str = "public, max-age=3600, must-revalidate";
|
||||
|
|
@ -416,15 +416,27 @@ async fn readme_handler(
|
|||
async fn issues_handler(
|
||||
State(ctx): State<Context>,
|
||||
Path(project): Path<Id>,
|
||||
Query(qs): Query<PaginationQuery>,
|
||||
Query(qs): Query<CobsQuery<api::IssueState>>,
|
||||
) -> impl IntoResponse {
|
||||
let PaginationQuery { page, per_page } = qs;
|
||||
let CobsQuery {
|
||||
page,
|
||||
per_page,
|
||||
state,
|
||||
} = qs;
|
||||
let page = page.unwrap_or(0);
|
||||
let per_page = per_page.unwrap_or(10);
|
||||
let state = state.unwrap_or_default();
|
||||
let storage = &ctx.profile.storage;
|
||||
let repo = storage.repository(project)?;
|
||||
let issues = issue::Issues::open(&repo)?;
|
||||
let mut issues: Vec<_> = issues.all()?.filter_map(|r| r.ok()).collect::<Vec<_>>();
|
||||
let mut issues: Vec<_> = issues
|
||||
.all()?
|
||||
.filter_map(|r| {
|
||||
let (id, issue, clock) = r.ok()?;
|
||||
(state.matches(issue.state())).then_some((id, issue, clock))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
issues.sort_by(|(_, a, _), (_, b, _)| b.timestamp().cmp(&a.timestamp()));
|
||||
let issues = issues
|
||||
.into_iter()
|
||||
|
|
@ -687,15 +699,26 @@ async fn patch_update_handler(
|
|||
async fn patches_handler(
|
||||
State(ctx): State<Context>,
|
||||
Path(project): Path<Id>,
|
||||
Query(qs): Query<PaginationQuery>,
|
||||
Query(qs): Query<CobsQuery<api::PatchState>>,
|
||||
) -> impl IntoResponse {
|
||||
let PaginationQuery { page, per_page } = qs;
|
||||
let CobsQuery {
|
||||
page,
|
||||
per_page,
|
||||
state,
|
||||
} = qs;
|
||||
let page = page.unwrap_or(0);
|
||||
let per_page = per_page.unwrap_or(10);
|
||||
let state = state.unwrap_or_default();
|
||||
let storage = &ctx.profile.storage;
|
||||
let repo = storage.repository(project)?;
|
||||
let patches = patch::Patches::open(&repo)?;
|
||||
let mut patches = patches.all()?.filter_map(|r| r.ok()).collect::<Vec<_>>();
|
||||
let mut patches = patches
|
||||
.all()?
|
||||
.filter_map(|r| {
|
||||
let (id, patch, clock) = r.ok()?;
|
||||
(state.matches(&patch.state())).then_some((id, patch, clock))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
patches.sort_by(|(_, a, _), (_, b, _)| b.timestamp().cmp(&a.timestamp()));
|
||||
let patches = patches
|
||||
.into_iter()
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl std::fmt::Display for State {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Closed { .. } => write!(f, "closed"),
|
||||
Self::Open { .. } => write!(f, "open"),
|
||||
Self::Open => write!(f, "open"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -71,8 +71,8 @@ impl std::fmt::Display for State {
|
|||
impl State {
|
||||
pub fn lifecycle_message(self) -> String {
|
||||
match self {
|
||||
State::Open => "Open issue".to_owned(),
|
||||
State::Closed { .. } => "Close issue".to_owned(),
|
||||
Self::Open => "Open issue".to_owned(),
|
||||
Self::Closed { .. } => "Close issue".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue