httpd: Add issue and patch counts

Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
This commit is contained in:
Sebastian Martinez 2023-02-24 11:43:00 -03:00 committed by Alexis Sellier
parent 5ea8505000
commit 97a2f8c1df
No known key found for this signature in database
5 changed files with 86 additions and 14 deletions

View File

@ -51,8 +51,8 @@ impl Context {
let doc = repo.identity_of(self.profile.id())?;
let payload = doc.project()?;
let delegates = doc.delegates;
let issues = (Issues::open(self.profile.public_key, &repo)?).count()?;
let patches = (Patches::open(self.profile.public_key, &repo)?).count()?;
let issues = Issues::open(self.profile.public_key, &repo)?.counts()?;
let patches = Patches::open(self.profile.public_key, &repo)?.counts()?;
Ok(project::Info {
payload,
@ -143,6 +143,7 @@ mod project {
use nonempty::NonEmpty;
use serde::Serialize;
use radicle::cob;
use radicle::git::Oid;
use radicle::identity::project::Project;
use radicle::identity::Id;
@ -157,8 +158,8 @@ mod project {
pub payload: Project,
pub delegates: NonEmpty<Did>,
pub head: Oid,
pub patches: usize,
pub issues: usize,
pub patches: cob::patch::PatchCounts,
pub issues: cob::issue::IssueCounts,
pub id: Id,
}
}

View File

@ -49,9 +49,9 @@ async fn delegates_projects_handler(
}
let Ok(issues) = Issues::open(ctx.profile.public_key, &repo) else { return None };
let Ok(issues) = (*issues).count() else { return None };
let Ok(issues) = issues.counts() else { return None };
let Ok(patches) = Patches::open(ctx.profile.public_key, &repo) else { return None };
let Ok(patches) = (*patches).count() else { return None };
let Ok(patches) = patches.counts() else { return None };
Some(Info {
payload,
@ -96,8 +96,15 @@ mod routes {
"defaultBranch": "master",
"delegates": ["did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"],
"head": HEAD,
"patches": 1,
"issues": 1,
"patches": {
"proposed": 1,
"draft": 0,
"archived": 0,
},
"issues": {
"open": 1,
"closed": 0,
},
"id": "rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp"
}
])

View File

@ -81,9 +81,9 @@ async fn project_root_handler(
let Ok(payload) = repo.project_of(ctx.profile.id()) else { return None };
let Ok(doc) = repo.identity_of(ctx.profile.id()) else { return None };
let Ok(issues) = Issues::open(ctx.profile.public_key, &repo) else { return None };
let Ok(issues) = (*issues).count() else { return None };
let Ok(issues) = issues.counts() else { return None };
let Ok(patches) = Patches::open(ctx.profile.public_key, &repo) else { return None };
let Ok(patches) = (*patches).count() else { return None };
let Ok(patches) = patches.counts() else { return None };
let delegates = doc.delegates;
Some(Info {
@ -583,8 +583,15 @@ mod routes {
"defaultBranch": "master",
"delegates": ["did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"],
"head": HEAD,
"patches": 1,
"issues": 1,
"patches": {
"proposed": 1,
"draft": 0,
"archived": 0,
},
"issues": {
"open": 1,
"closed": 0,
},
"id": "rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp"
}
])
@ -606,8 +613,15 @@ mod routes {
"defaultBranch": "master",
"delegates": ["did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"],
"head": HEAD,
"patches": 1,
"issues": 1,
"patches": {
"proposed": 1,
"draft": 0,
"archived": 0,
},
"issues": {
"open": 1,
"closed": 0,
},
"id": "rad:z4FucBZHZMCsxTyQE1dfE2YR59Qbp"
})
);

View File

@ -385,6 +385,14 @@ impl<'a> Deref for Issues<'a> {
}
}
/// Detailed information on issue states
#[derive(Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct IssueCounts {
pub open: usize,
pub closed: usize,
}
impl<'a> Issues<'a> {
/// Open an issues store.
pub fn open(
@ -443,6 +451,22 @@ impl<'a> Issues<'a> {
})
}
/// Issues count by state.
pub fn counts(&self) -> Result<IssueCounts, Error> {
let all = self.all()?;
let state_groups =
all.filter_map(|s| s.ok())
.fold(IssueCounts::default(), |mut state, (_, p, _)| {
match p.state() {
State::Open => state.open += 1,
State::Closed { .. } => state.closed += 1,
}
state
});
Ok(state_groups)
}
/// Remove an issue.
pub fn remove(&self, id: &ObjectId) -> Result<(), store::Error> {
self.raw.remove(id)

View File

@ -758,6 +758,15 @@ impl<'a, 'g> Deref for PatchMut<'a, 'g> {
}
}
/// Detailed information on patch states
#[derive(Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PatchCounts {
pub proposed: usize,
pub draft: usize,
pub archived: usize,
}
pub struct Patches<'a> {
raw: store::Store<'a, Patch>,
}
@ -804,6 +813,23 @@ impl<'a> Patches<'a> {
Ok(PatchMut::new(id, patch, clock, self))
}
/// Patches count by state.
pub fn counts(&self) -> Result<PatchCounts, store::Error> {
let all = self.all()?;
let state_groups =
all.filter_map(|s| s.ok())
.fold(PatchCounts::default(), |mut state, (_, p, _)| {
match p.state() {
State::Draft => state.draft += 1,
State::Proposed => state.proposed += 1,
State::Archived => state.archived += 1,
}
state
});
Ok(state_groups)
}
/// Get a patch.
pub fn get(&self, id: &ObjectId) -> Result<Option<Patch>, store::Error> {
self.raw.get(id).map(|r| r.map(|(p, _)| p))