101 lines
3.2 KiB
Rust
101 lines
3.2 KiB
Rust
use db::sqlx;
|
|
use model::issues::LabelModel;
|
|
use serde::Deserialize;
|
|
use session::Session;
|
|
use uuid::Uuid;
|
|
|
|
use crate::{
|
|
AppService, error::AppError, issues::types::LabelResponse, session_user,
|
|
};
|
|
|
|
#[derive(Debug, Clone, Deserialize, utoipa::ToSchema)]
|
|
pub struct AddPrLabel {
|
|
pub label_id: Uuid,
|
|
}
|
|
|
|
impl AppService {
|
|
pub async fn pr_add_label(
|
|
&self,
|
|
ctx: &Session,
|
|
wk_name: &str,
|
|
repo_name: &str,
|
|
number: i64,
|
|
params: AddPrLabel,
|
|
) -> Result<Vec<LabelResponse>, AppError> {
|
|
let user_uid = session_user(ctx)?;
|
|
let wk = self.workspace_resolve(wk_name).await?;
|
|
self.workspace_require_member(wk.id, user_uid).await?;
|
|
let repo = self.repo_resolve(wk.id, repo_name).await?;
|
|
let pr = self.pr_resolve(repo.id, number).await?;
|
|
|
|
let _label = sqlx::query_as::<_, LabelModel>(
|
|
"SELECT id, wk, name, color, description, created_at, updated_at, deleted_at \
|
|
FROM label WHERE id = $1 AND wk = $2 AND deleted_at IS NULL",
|
|
)
|
|
.bind(params.label_id)
|
|
.bind(wk.id)
|
|
.fetch_optional(self.db.reader())
|
|
.await
|
|
.map_err(|e| AppError::DatabaseError(e.to_string()))?
|
|
.ok_or(AppError::LabelNotFound)?;
|
|
|
|
sqlx::query(
|
|
"INSERT INTO pull_request_label (pull_request, label, created_at) VALUES ($1, $2, $3) \
|
|
ON CONFLICT (pull_request, label) DO NOTHING",
|
|
)
|
|
.bind(pr.id)
|
|
.bind(params.label_id)
|
|
.bind(chrono::Utc::now())
|
|
.execute(self.db.writer())
|
|
.await
|
|
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
|
|
|
|
self.pr_labels(pr.id).await
|
|
}
|
|
|
|
pub async fn pr_remove_label(
|
|
&self,
|
|
ctx: &Session,
|
|
wk_name: &str,
|
|
repo_name: &str,
|
|
number: i64,
|
|
label_id: Uuid,
|
|
) -> Result<Vec<LabelResponse>, AppError> {
|
|
let user_uid = session_user(ctx)?;
|
|
let wk = self.workspace_resolve(wk_name).await?;
|
|
self.workspace_require_member(wk.id, user_uid).await?;
|
|
let repo = self.repo_resolve(wk.id, repo_name).await?;
|
|
let pr = self.pr_resolve(repo.id, number).await?;
|
|
|
|
sqlx::query("DELETE FROM pull_request_label WHERE pull_request = $1 AND label = $2")
|
|
.bind(pr.id)
|
|
.bind(label_id)
|
|
.execute(self.db.writer())
|
|
.await
|
|
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
|
|
|
|
self.pr_labels(pr.id).await
|
|
}
|
|
|
|
pub async fn pr_labels(
|
|
&self,
|
|
pr_id: uuid::Uuid,
|
|
) -> Result<Vec<LabelResponse>, AppError> {
|
|
let labels = sqlx::query_as::<_, LabelModel>(
|
|
"SELECT l.id, l.wk, l.name, l.color, l.description, l.created_at, l.updated_at, l.deleted_at \
|
|
FROM pull_request_label pl INNER JOIN label l ON l.id = pl.label \
|
|
WHERE pl.pull_request = $1 AND l.deleted_at IS NULL \
|
|
ORDER BY l.name ASC",
|
|
)
|
|
.bind(pr_id)
|
|
.fetch_all(self.db.reader())
|
|
.await
|
|
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
|
|
|
|
Ok(labels
|
|
.into_iter()
|
|
.map(crate::issues::types::label_response)
|
|
.collect())
|
|
}
|
|
}
|