147 lines
4.9 KiB
Rust
147 lines
4.9 KiB
Rust
use chrono::Utc;
|
|
use uuid::Uuid;
|
|
|
|
use crate::event::{UserInfo, WorkspaceInfo, category};
|
|
use crate::{ChannelBus, ChannelError, ChannelResult};
|
|
|
|
use super::MAX_CATEGORY_NAME_LEN;
|
|
use super::WsHandler;
|
|
use super::WsOutEvent;
|
|
|
|
impl WsHandler {
|
|
pub(super) async fn category_create(
|
|
bus: &ChannelBus,
|
|
user_id: Uuid,
|
|
workspace: Uuid,
|
|
name: String,
|
|
position: Option<i32>,
|
|
) -> ChannelResult<Option<WsOutEvent>> {
|
|
if name.is_empty() || name.len() > MAX_CATEGORY_NAME_LEN {
|
|
return Err(ChannelError::Validation(
|
|
"invalid category name".into(),
|
|
));
|
|
}
|
|
Self::ensure_workspace_member(bus, user_id, workspace).await?;
|
|
let row = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
|
|
"INSERT INTO room_category (wk, name, position, created_at, updated_at) \
|
|
VALUES ($1, $2, $3, now(), now()) \
|
|
RETURNING id, wk, name, position, collapsed, created_at, updated_at",
|
|
)
|
|
.bind(workspace)
|
|
.bind(&name)
|
|
.bind(position.unwrap_or(0))
|
|
.fetch_one(bus.inner.db.writer())
|
|
.await?;
|
|
let cc_workspace = bus
|
|
.lookup_workspace(workspace)
|
|
.await
|
|
.unwrap_or_else(|_| WorkspaceInfo::unknown(workspace));
|
|
let cc_user = bus
|
|
.lookup_user(user_id)
|
|
.await
|
|
.unwrap_or_else(|_| UserInfo::unknown(user_id));
|
|
let data = category::CategoryCreatedService {
|
|
id: row.id,
|
|
project: cc_workspace,
|
|
name: row.name,
|
|
position: row.position,
|
|
created_by: cc_user,
|
|
created_at: row.created_at,
|
|
};
|
|
bus.workspace_changed(workspace).await?;
|
|
Ok(Some(WsOutEvent::CategoryCreated {
|
|
workspace: data.project.clone(),
|
|
data,
|
|
}))
|
|
}
|
|
|
|
pub(super) async fn category_update(
|
|
bus: &ChannelBus,
|
|
user_id: Uuid,
|
|
id: Uuid,
|
|
name: Option<String>,
|
|
position: Option<i32>,
|
|
) -> ChannelResult<Option<WsOutEvent>> {
|
|
let old = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
|
|
"SELECT id, wk, name, position, collapsed, created_at, updated_at \
|
|
FROM room_category WHERE id = $1",
|
|
)
|
|
.bind(id)
|
|
.fetch_one(bus.inner.db.reader())
|
|
.await?;
|
|
Self::ensure_workspace_member(bus, user_id, old.wk).await?;
|
|
let new_name = name.unwrap_or(old.name.clone());
|
|
let new_position = position.unwrap_or(old.position);
|
|
db::sqlx::query(
|
|
"UPDATE room_category SET name = $2, position = $3, updated_at = now() WHERE id = $1",
|
|
)
|
|
.bind(id)
|
|
.bind(&new_name)
|
|
.bind(new_position)
|
|
.execute(bus.inner.db.writer())
|
|
.await?;
|
|
let cu_workspace = bus
|
|
.lookup_workspace(old.wk)
|
|
.await
|
|
.unwrap_or_else(|_| WorkspaceInfo::unknown(old.wk));
|
|
let cu_user = bus
|
|
.lookup_user(user_id)
|
|
.await
|
|
.unwrap_or_else(|_| UserInfo::unknown(user_id));
|
|
let data = category::CategoryUpdatedService {
|
|
id,
|
|
project: cu_workspace,
|
|
name: Some(new_name),
|
|
position: Some(new_position),
|
|
updated_by: cu_user,
|
|
updated_at: Utc::now(),
|
|
};
|
|
bus.workspace_changed(old.wk).await?;
|
|
Ok(Some(WsOutEvent::CategoryUpdated {
|
|
workspace: data.project.clone(),
|
|
data,
|
|
}))
|
|
}
|
|
|
|
pub(super) async fn category_delete(
|
|
bus: &ChannelBus,
|
|
_user_id: Uuid,
|
|
id: Uuid,
|
|
) -> ChannelResult<Option<WsOutEvent>> {
|
|
let existing = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
|
|
"SELECT id, wk, name, position, collapsed, created_at, updated_at \
|
|
FROM room_category WHERE id = $1",
|
|
)
|
|
.bind(id)
|
|
.fetch_one(bus.inner.db.reader())
|
|
.await?;
|
|
Self::ensure_workspace_member(bus, _user_id, existing.wk).await?;
|
|
let row = db::sqlx::query_as::<_, model::room::RoomCategoryModel>(
|
|
"DELETE FROM room_category WHERE id = $1 \
|
|
RETURNING id, wk, name, position, collapsed, created_at, updated_at",
|
|
)
|
|
.bind(id)
|
|
.fetch_one(bus.inner.db.writer())
|
|
.await?;
|
|
let cd_workspace = bus
|
|
.lookup_workspace(row.wk)
|
|
.await
|
|
.unwrap_or_else(|_| WorkspaceInfo::unknown(row.wk));
|
|
let cd_user = bus
|
|
.lookup_user(_user_id)
|
|
.await
|
|
.unwrap_or_else(|_| UserInfo::unknown(_user_id));
|
|
let data = category::CategoryDeletedService {
|
|
id: row.id,
|
|
project: cd_workspace.clone(),
|
|
deleted_by: cd_user,
|
|
deleted_at: Utc::now(),
|
|
};
|
|
bus.workspace_changed(row.wk).await?;
|
|
Ok(Some(WsOutEvent::CategoryDeleted {
|
|
workspace: cd_workspace,
|
|
data,
|
|
}))
|
|
}
|
|
}
|