d5939db
use db::project::project_views as view_entity;
use db::project::project_views::Column as Vc;
use sea_orm::{
ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, QueryOrder, Set,
};
use time::OffsetDateTime;
use uuid::Uuid;
use crate::error::{ProjectError, ProjectResult};
use crate::features::lifecycle::usecase::log_activity;
use crate::features::ProjectService;
use crate::permission;
use super::{CreateViewCmd, UpdateViewCmd, ViewPage, ViewView};
pub async fn create_view(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
cmd: CreateViewCmd,
) -> ProjectResult<ViewView> {
crate::features::authz::require(
svc,
actor,
space_id,
project_id,
permission::MANAGE_VIEWS,
)
.await?;
let id = Uuid::new_v4();
let now = OffsetDateTime::now_utc();
let row = view_entity::ActiveModel {
id: Set(id),
project_id: Set(project_id),
creator_id: Set(actor),
name: Set(cmd.name),
description: Set(cmd.description),
filter: Set(cmd.filter),
sort_by: Set(cmd.sort_by),
group_by: Set(cmd.group_by),
layout: Set(cmd.layout),
is_shared: Set(cmd.is_shared),
sort_order: Set(0),
created_at: Set(now),
updated_at: Set(None),
}
.insert(&svc.db.writer())
.await?;
log_activity(svc, project_id, actor, "view_created", "view", Some(id), None).await;
Ok(view_view(&row))
}
pub async fn list_views(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
) -> ProjectResult<ViewPage> {
crate::features::authz::require(svc, actor, space_id, project_id, permission::VIEW_PROJECT)
.await?;
let rows = view_entity::Entity::find()
.filter(Vc::ProjectId.eq(project_id))
.order_by_asc(Vc::SortOrder)
.order_by_desc(Vc::CreatedAt)
.all(&svc.db.reader())
.await?;
let items = rows.iter().map(view_view).collect::<Vec<_>>();
let total = items.len() as u64;
Ok(ViewPage { total, items })
}
pub async fn get_view(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
view_id: Uuid,
) -> ProjectResult<ViewView> {
crate::features::authz::require(svc, actor, space_id, project_id, permission::VIEW_PROJECT)
.await?;
let row = view_entity::Entity::find_by_id(view_id)
.filter(Vc::ProjectId.eq(project_id))
.one(&svc.db.reader())
.await?
.ok_or_else(|| ProjectError::NotFound(format!("view {view_id} in project {project_id}")))?;
Ok(view_view(&row))
}
pub async fn update_view(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
view_id: Uuid,
cmd: UpdateViewCmd,
) -> ProjectResult<ViewView> {
crate::features::authz::require(
svc,
actor,
space_id,
project_id,
permission::MANAGE_VIEWS,
)
.await?;
let current = view_entity::Entity::find_by_id(view_id)
.filter(Vc::ProjectId.eq(project_id))
.one(&svc.db.reader())
.await?
.ok_or_else(|| ProjectError::NotFound(format!("view {view_id} in project {project_id}")))?;
let mut active: view_entity::ActiveModel = current.into();
if let Some(name) = cmd.name {
active.name = Set(name);
}
if cmd.description.is_some() {
active.description = Set(cmd.description);
}
if let Some(filter) = cmd.filter {
active.filter = Set(filter);
}
if let Some(sort_by) = cmd.sort_by {
active.sort_by = Set(sort_by);
}
if cmd.group_by.is_some() {
active.group_by = Set(cmd.group_by);
}
if let Some(layout) = cmd.layout {
active.layout = Set(layout);
}
if let Some(shared) = cmd.is_shared {
active.is_shared = Set(shared);
}
active.updated_at = Set(Some(OffsetDateTime::now_utc()));
let updated = active.update(&svc.db.writer()).await?;
log_activity(svc, project_id, actor, "view_updated", "view", Some(view_id), None).await;
Ok(view_view(&updated))
}
pub async fn delete_view(
svc: &ProjectService,
actor: Uuid,
space_id: Uuid,
project_id: Uuid,
view_id: Uuid,
) -> ProjectResult<()> {
crate::features::authz::require(
svc,
actor,
space_id,
project_id,
permission::MANAGE_VIEWS,
)
.await?;
let deleted = view_entity::Entity::delete_many()
.filter(Vc::Id.eq(view_id))
.filter(Vc::ProjectId.eq(project_id))
.exec(&svc.db.writer())
.await?;
if deleted.rows_affected == 0 {
return Err(ProjectError::NotFound(format!(
"view {view_id} in project {project_id}"
)));
}
log_activity(svc, project_id, actor, "view_deleted", "view", Some(view_id), None).await;
Ok(())
}
fn view_view(m: &view_entity::Model) -> ViewView {
ViewView {
id: m.id,
project_id: m.project_id,
creator_id: m.creator_id,
name: m.name.clone(),
description: m.description.clone(),
filter: m.filter.clone(),
sort_by: m.sort_by.clone(),
group_by: m.group_by.clone(),
layout: m.layout.clone(),
is_shared: m.is_shared,
sort_order: m.sort_order,
created_at: m.created_at,
updated_at: m.updated_at,
}
}