src/server/http/repo/patches.rs
Ref: Size: 5.0 KiB
use std::sync::Arc;
use axum::extract::{Path, State};
use axum::response::{IntoResponse, Response};
use super::{AppState, CommentView, collab_counts, internal_error, not_found, open_repo};
#[derive(Debug)]
pub struct PatchListItem {
pub id: String,
pub short_id: String,
pub status: String,
pub title: String,
pub author: String,
pub branch: String,
pub updated: String,
}
#[derive(askama::Template, askama_web::WebTemplate)]
#[template(path = "patches.html")]
pub struct PatchesTemplate {
pub site_title: String,
pub repo_name: String,
pub active_section: String,
pub open_patches: usize,
pub open_issues: usize,
pub patches: Vec<PatchListItem>,
}
#[derive(Debug)]
pub struct RevisionView {
pub number: u32,
pub commit: String,
pub timestamp: String,
pub body: Option<String>,
}
#[derive(Debug)]
pub struct ReviewView {
pub author: String,
pub verdict: String,
pub body: String,
pub timestamp: String,
pub revision: Option<u32>,
}
#[derive(Debug)]
pub struct InlineCommentView {
pub author: String,
pub file: String,
pub line: u32,
pub body: String,
pub timestamp: String,
pub revision: Option<u32>,
}
#[derive(Debug)]
pub struct PatchDetailView {
pub title: String,
pub body: String,
pub status: String,
pub author: String,
pub branch: String,
pub base_ref: String,
pub revisions: Vec<RevisionView>,
pub reviews: Vec<ReviewView>,
pub inline_comments: Vec<InlineCommentView>,
pub comments: Vec<CommentView>,
}
#[derive(askama::Template, askama_web::WebTemplate)]
#[template(path = "patch_detail.html")]
pub struct PatchDetailTemplate {
pub site_title: String,
pub repo_name: String,
pub active_section: String,
pub open_patches: usize,
pub open_issues: usize,
pub patch: PatchDetailView,
}
pub async fn patches(
Path(repo_name): Path<String>,
State(state): State<Arc<AppState>>,
) -> Response {
let (_entry, repo) = match open_repo(&state, &repo_name) {
Ok(r) => r,
Err(resp) => return resp,
};
let (open_patches, open_issues) = collab_counts(&repo);
let all_patches = git_collab::state::list_patches_with_archived(&repo).unwrap_or_default();
let patches = all_patches
.into_iter()
.map(|p| {
let id = p.id.clone();
let short_id = id[..8.min(id.len())].to_string();
PatchListItem {
short_id,
id,
status: p.status.as_str().to_string(),
title: p.title,
author: p.author.name,
branch: p.branch,
updated: p.last_updated,
}
})
.collect();
PatchesTemplate {
site_title: state.site_title.clone(),
repo_name,
active_section: "patches".to_string(),
open_patches,
open_issues,
patches,
}
.into_response()
}
pub async fn patch_detail(
Path((repo_name, patch_id)): Path<(String, String)>,
State(state): State<Arc<AppState>>,
) -> Response {
let (_entry, repo) = match open_repo(&state, &repo_name) {
Ok(r) => r,
Err(resp) => return resp,
};
let (open_patches, open_issues) = collab_counts(&repo);
let (ref_name, full_id) = match git_collab::state::resolve_patch_ref(&repo, &patch_id) {
Ok(r) => r,
Err(_) => return not_found(&state, format!("Patch '{}' not found.", patch_id)),
};
let ps = match git_collab::state::PatchState::from_ref(&repo, &ref_name, &full_id) {
Ok(s) => s,
Err(_) => return internal_error(&state, "Failed to load patch state."),
};
let patch = PatchDetailView {
title: ps.title,
body: ps.body,
status: ps.status.as_str().to_string(),
author: ps.author.name,
branch: ps.branch,
base_ref: ps.base_ref,
revisions: ps.revisions.into_iter().map(|r| RevisionView {
number: r.number,
commit: r.commit,
timestamp: r.timestamp,
body: r.body,
}).collect(),
reviews: ps.reviews.into_iter().map(|r| ReviewView {
author: r.author.name,
verdict: r.verdict.as_str().to_string(),
body: r.body,
timestamp: r.timestamp,
revision: r.revision,
}).collect(),
inline_comments: ps.inline_comments.into_iter().map(|ic| InlineCommentView {
author: ic.author.name,
file: ic.file,
line: ic.line,
body: ic.body,
timestamp: ic.timestamp,
revision: ic.revision,
}).collect(),
comments: ps.comments.into_iter().map(|c| CommentView {
author: c.author.name,
body: c.body,
timestamp: c.timestamp,
}).collect(),
};
PatchDetailTemplate {
site_title: state.site_title.clone(),
repo_name,
active_section: "patches".to_string(),
open_patches,
open_issues,
patch,
}
.into_response()
}