use axum::{
extract::{Path, State},
response::IntoResponse,
Json,
};
use sea_orm::{ActiveModelTrait, ActiveValue, ColumnTrait, EntityTrait, QueryFilter};
use validator::Validate;
use crate::{error::ApiResult, state::AppState};
use super::{CreateProjectRequest, Project, UpdateProjectRequest};
pub async fn list_projects(State(state): State<AppState>) -> ApiResult<impl IntoResponse> {
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "projects")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
pub name: String,
pub description: Option<String>,
pub repository_url: Option<String>,
pub status: String,
pub created_at: ChronoDateTimeUtc,
pub updated_at: ChronoDateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
let projects = Entity::find()
.all(&state.db)
.await?
.into_iter()
.map(|p| Project {
id: p.id,
name: p.name,
description: p.description,
repository_url: p.repository_url,
status: p.status,
created_at: p.created_at,
updated_at: p.updated_at,
})
.collect::<Vec<_>>();
Ok(Json(projects))
}
pub async fn get_project(
State(state): State<AppState>,
Path(id): Path<i64>,
) -> ApiResult<impl IntoResponse> {
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "projects")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
pub name: String,
pub description: Option<String>,
pub repository_url: Option<String>,
pub status: String,
pub created_at: ChronoDateTimeUtc,
pub updated_at: ChronoDateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
let project = Entity::find_by_id(id)
.one(&state.db)
.await?
.ok_or_else(|| crate::error::AppError::NotFound(format!("Project {} not found", id)))?;
Ok(Json(Project {
id: project.id,
name: project.name,
description: project.description,
repository_url: project.repository_url,
status: project.status,
created_at: project.created_at,
updated_at: project.updated_at,
}))
}
pub async fn create_project(
State(state): State<AppState>,
Json(req): Json<CreateProjectRequest>,
) -> ApiResult<impl IntoResponse> {
req.validate()?;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "projects")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
pub name: String,
pub description: Option<String>,
pub repository_url: Option<String>,
pub status: String,
pub created_at: ChronoDateTimeUtc,
pub updated_at: ChronoDateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
let now = chrono::Utc::now();
let project = ActiveModel {
name: ActiveValue::Set(req.name),
description: ActiveValue::Set(req.description),
repository_url: ActiveValue::Set(req.repository_url),
status: ActiveValue::Set("active".to_string()),
created_at: ActiveValue::Set(now),
updated_at: ActiveValue::Set(now),
..Default::default()
};
let project = project.insert(&state.db).await?;
Ok(Json(Project {
id: project.id,
name: project.name,
description: project.description,
repository_url: project.repository_url,
status: project.status,
created_at: project.created_at,
updated_at: project.updated_at,
}))
}
pub async fn update_project(
State(state): State<AppState>,
Path(id): Path<i64>,
Json(req): Json<UpdateProjectRequest>,
) -> ApiResult<impl IntoResponse> {
req.validate()?;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "projects")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
pub name: String,
pub description: Option<String>,
pub repository_url: Option<String>,
pub status: String,
pub created_at: ChronoDateTimeUtc,
pub updated_at: ChronoDateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
let project = Entity::find_by_id(id)
.one(&state.db)
.await?
.ok_or_else(|| crate::error::AppError::NotFound(format!("Project {} not found", id)))?;
let mut project: ActiveModel = project.into();
if let Some(name) = req.name {
project.name = ActiveValue::Set(name);
}
if let Some(description) = req.description {
project.description = ActiveValue::Set(Some(description));
}
if let Some(repository_url) = req.repository_url {
project.repository_url = ActiveValue::Set(Some(repository_url));
}
if let Some(status) = req.status {
project.status = ActiveValue::Set(status);
}
project.updated_at = ActiveValue::Set(chrono::Utc::now());
let project = project.update(&state.db).await?;
Ok(Json(Project {
id: project.id,
name: project.name,
description: project.description,
repository_url: project.repository_url,
status: project.status,
created_at: project.created_at,
updated_at: project.updated_at,
}))
}
pub async fn delete_project(
State(state): State<AppState>,
Path(id): Path<i64>,
) -> ApiResult<impl IntoResponse> {
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "projects")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
pub name: String,
pub description: Option<String>,
pub repository_url: Option<String>,
pub status: String,
pub created_at: ChronoDateTimeUtc,
pub updated_at: ChronoDateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
let project = Entity::find_by_id(id)
.one(&state.db)
.await?
.ok_or_else(|| crate::error::AppError::NotFound(format!("Project {} not found", id)))?;
let project: ActiveModel = project.into();
project.delete(&state.db).await?;
Ok(Json(serde_json::json!({
"message": "Project deleted successfully"
})))
}