Add milestone creation and editing

This commit is contained in:
Georg Bauer
2026-07-31 15:30:45 +02:00
parent da0a3aecb4
commit c4e64b5c0c
13 changed files with 591 additions and 21 deletions

View File

@@ -3,14 +3,15 @@ use std::{
collections::{BTreeSet, BinaryHeap, HashMap},
};
use gotcha_gitea::{Client, apis, models};
use gotcha_gitea::{Client, Method, apis, models};
use serde::Serialize;
use tokio::task::JoinSet;
use crate::{
diff,
domain::{
HistoryCommit, HomeData, IssueDetails, IssueDraft, IssueEditorData, MilestoneDetails,
PAGE_SIZE, Page, PullDetails, RepositoryData, Server, api_date,
MilestoneDraft, PAGE_SIZE, Page, PullDetails, RepositoryData, Server, api_date,
},
presentation::compact_date,
};
@@ -229,6 +230,80 @@ pub async fn load_milestone(
})
}
pub async fn load_milestone_editor(
server: &Server,
owner: &str,
repository: &str,
id: i64,
) -> Result<models::Milestone, String> {
let client =
Client::new(&server.url, Some(&server.token)).map_err(|error| error.to_string())?;
apis::issue_api::issue_get_milestone(
&client.configuration(),
owner,
repository,
&id.to_string(),
)
.await
.map_err(|error| error.to_string())
}
#[derive(Serialize)]
struct MilestoneRequest {
title: String,
description: String,
due_on: Option<String>,
}
fn milestone_request(draft: MilestoneDraft) -> MilestoneRequest {
MilestoneRequest {
title: draft.title,
description: draft.description,
due_on: draft.due_date.map(api_date),
}
}
pub async fn save_milestone(
server: &Server,
owner: &str,
repository: &str,
id: Option<i64>,
draft: MilestoneDraft,
) -> Result<models::Milestone, String> {
let client =
Client::new(&server.url, Some(&server.token)).map_err(|error| error.to_string())?;
let endpoint = match id {
Some(id) => format!(
"repos/{}/{}/milestones/{id}",
apis::urlencode(owner),
apis::urlencode(repository)
),
None => format!(
"repos/{}/{}/milestones",
apis::urlencode(owner),
apis::urlencode(repository)
),
};
let request = client
.request(
if id.is_some() {
Method::PATCH
} else {
Method::POST
},
&endpoint,
)
.map_err(|error| error.to_string())?
.json(&milestone_request(draft));
client
.execute(request)
.await
.map_err(|error| error.to_string())?
.json()
.await
.map_err(|error| error.to_string())
}
pub async fn load_pulls(
server: &Server,
status: &str,
@@ -1115,4 +1190,25 @@ mod tests {
assert!(!comment_belongs_to_issue(&comment, 5));
assert!(!comment_belongs_to_issue(&models::Comment::default(), 4));
}
#[test]
fn milestone_requests_can_set_and_clear_due_dates() {
let dated = serde_json::to_value(milestone_request(MilestoneDraft {
title: "Version 1".into(),
description: "Description".into(),
due_date: Some(1_709_164_800),
}))
.unwrap();
assert_eq!(dated["title"], "Version 1");
assert_eq!(dated["description"], "Description");
assert_eq!(dated["due_on"], "2024-02-29T00:00:00Z");
let cleared = serde_json::to_value(milestone_request(MilestoneDraft {
title: "Version 1".into(),
description: String::new(),
due_date: None,
}))
.unwrap();
assert!(cleared["due_on"].is_null());
}
}