From 7abba9d7efe76453d3f9aa7036d10f4592888686 Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Tue, 27 Feb 2024 11:26:31 +0800 Subject: [PATCH] feat: add workspace icon field --- ...905442985f7cfa19faaaa970a410708adc773.json | 8 ++++- ...52273aa959b610ca3d5e4f8eaecf4f7785dc2.json | 8 ++++- ...90442ba1a49ddb811f89faa8ba1459e17ca86.json | 8 ++++- ...abe5a46d40b9bff68df3896adc5348539d27b.json | 8 ++++- libs/database-entity/src/dto.rs | 1 + libs/database/src/pg_row.rs | 3 ++ libs/database/src/workspace.rs | 27 ++++++++++++++++ libs/shared-entity/src/dto/workspace_dto.rs | 3 +- src/api/workspace.rs | 1 + src/biz/workspace/ops.rs | 6 +++- tests/workspace/workspace_crud.rs | 32 ++++++++++++++++++- 11 files changed, 98 insertions(+), 7 deletions(-) diff --git a/.sqlx/query-03b8ab1c98353b442f9c143c29a905442985f7cfa19faaaa970a410708adc773.json b/.sqlx/query-03b8ab1c98353b442f9c143c29a905442985f7cfa19faaaa970a410708adc773.json index fafa4176..2a9066dd 100644 --- a/.sqlx/query-03b8ab1c98353b442f9c143c29a905442985f7cfa19faaaa970a410708adc773.json +++ b/.sqlx/query-03b8ab1c98353b442f9c143c29a905442985f7cfa19faaaa970a410708adc773.json @@ -37,6 +37,11 @@ "ordinal": 6, "name": "workspace_name", "type_info": "Text" + }, + { + "ordinal": 7, + "name": "icon", + "type_info": "Text" } ], "parameters": { @@ -51,7 +56,8 @@ true, false, true, - true + true, + false ] }, "hash": "03b8ab1c98353b442f9c143c29a905442985f7cfa19faaaa970a410708adc773" diff --git a/.sqlx/query-0517066279a74e9af59645b8bb152273aa959b610ca3d5e4f8eaecf4f7785dc2.json b/.sqlx/query-0517066279a74e9af59645b8bb152273aa959b610ca3d5e4f8eaecf4f7785dc2.json index 1ee4e167..4a10e9e6 100644 --- a/.sqlx/query-0517066279a74e9af59645b8bb152273aa959b610ca3d5e4f8eaecf4f7785dc2.json +++ b/.sqlx/query-0517066279a74e9af59645b8bb152273aa959b610ca3d5e4f8eaecf4f7785dc2.json @@ -37,6 +37,11 @@ "ordinal": 6, "name": "workspace_name", "type_info": "Text" + }, + { + "ordinal": 7, + "name": "icon", + "type_info": "Text" } ], "parameters": { @@ -51,7 +56,8 @@ true, false, true, - true + true, + false ] }, "hash": "0517066279a74e9af59645b8bb152273aa959b610ca3d5e4f8eaecf4f7785dc2" diff --git a/.sqlx/query-5506d75e81326efb146326c929e90442ba1a49ddb811f89faa8ba1459e17ca86.json b/.sqlx/query-5506d75e81326efb146326c929e90442ba1a49ddb811f89faa8ba1459e17ca86.json index cf753933..665d3e08 100644 --- a/.sqlx/query-5506d75e81326efb146326c929e90442ba1a49ddb811f89faa8ba1459e17ca86.json +++ b/.sqlx/query-5506d75e81326efb146326c929e90442ba1a49ddb811f89faa8ba1459e17ca86.json @@ -37,6 +37,11 @@ "ordinal": 6, "name": "workspace_name", "type_info": "Text" + }, + { + "ordinal": 7, + "name": "icon", + "type_info": "Text" } ], "parameters": { @@ -52,7 +57,8 @@ true, false, true, - true + true, + false ] }, "hash": "5506d75e81326efb146326c929e90442ba1a49ddb811f89faa8ba1459e17ca86" diff --git a/.sqlx/query-af5c5c1fbf22870171f644e70b0abe5a46d40b9bff68df3896adc5348539d27b.json b/.sqlx/query-af5c5c1fbf22870171f644e70b0abe5a46d40b9bff68df3896adc5348539d27b.json index 0eb5b70c..7cc014fe 100644 --- a/.sqlx/query-af5c5c1fbf22870171f644e70b0abe5a46d40b9bff68df3896adc5348539d27b.json +++ b/.sqlx/query-af5c5c1fbf22870171f644e70b0abe5a46d40b9bff68df3896adc5348539d27b.json @@ -37,6 +37,11 @@ "ordinal": 6, "name": "workspace_name", "type_info": "Text" + }, + { + "ordinal": 7, + "name": "icon", + "type_info": "Text" } ], "parameters": { @@ -51,7 +56,8 @@ true, false, true, - true + true, + false ] }, "hash": "af5c5c1fbf22870171f644e70b0abe5a46d40b9bff68df3896adc5348539d27b" diff --git a/libs/database-entity/src/dto.rs b/libs/database-entity/src/dto.rs index d13b5f9b..3f8c6899 100644 --- a/libs/database-entity/src/dto.rs +++ b/libs/database-entity/src/dto.rs @@ -444,6 +444,7 @@ pub struct AFWorkspace { pub workspace_type: i32, pub workspace_name: String, pub created_at: DateTime, + pub icon: String, } #[derive(Serialize, Deserialize)] diff --git a/libs/database/src/pg_row.rs b/libs/database/src/pg_row.rs index b31b01b7..302e7cec 100644 --- a/libs/database/src/pg_row.rs +++ b/libs/database/src/pg_row.rs @@ -16,6 +16,7 @@ pub struct AFWorkspaceRow { pub workspace_type: i32, pub deleted_at: Option>, pub workspace_name: Option, + pub icon: Option, } impl TryFrom for AFWorkspace { @@ -31,6 +32,7 @@ impl TryFrom for AFWorkspace { let workspace_name = value.workspace_name.unwrap_or_default(); let created_at = value.created_at.unwrap_or_else(Utc::now); + let icon = value.icon.unwrap_or_default(); Ok(Self { workspace_id: value.workspace_id, @@ -39,6 +41,7 @@ impl TryFrom for AFWorkspace { workspace_type: value.workspace_type, workspace_name, created_at, + icon, }) } } diff --git a/libs/database/src/workspace.rs b/libs/database/src/workspace.rs index 00141945..84f8dc13 100644 --- a/libs/database/src/workspace.rs +++ b/libs/database/src/workspace.rs @@ -73,6 +73,33 @@ pub async fn rename_workspace( Ok(()) } +#[inline] +pub async fn change_workspace_icon( + tx: &mut Transaction<'_, sqlx::Postgres>, + workspace_id: &Uuid, + icon: &str, +) -> Result<(), AppError> { + let res = sqlx::query!( + r#" + UPDATE public.af_workspace + SET icon = $1 + WHERE workspace_id = $2 + "#, + icon, + workspace_id, + ) + .execute(tx.deref_mut()) + .await?; + + if res.rows_affected() != 1 { + tracing::error!( + "Failed to change workspace icon, workspace_id: {}", + workspace_id + ); + } + Ok(()) +} + /// Checks whether a user, identified by a UUID, is an 'Owner' of a workspace, identified by its /// workspace_id. #[inline] diff --git a/libs/shared-entity/src/dto/workspace_dto.rs b/libs/shared-entity/src/dto/workspace_dto.rs index 68b815b0..95ac11d7 100644 --- a/libs/shared-entity/src/dto/workspace_dto.rs +++ b/libs/shared-entity/src/dto/workspace_dto.rs @@ -83,8 +83,9 @@ pub struct CreateWorkspaceParam { pub workspace_name: Option, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Default)] pub struct PatchWorkspaceParam { pub workspace_id: Uuid, pub workspace_name: Option, + pub workspace_icon: Option, } diff --git a/src/api/workspace.rs b/src/api/workspace.rs index 3c16f7e4..f63d96e9 100644 --- a/src/api/workspace.rs +++ b/src/api/workspace.rs @@ -153,6 +153,7 @@ async fn patch_workspace_handler( &state.pg_pool, ¶ms.workspace_id, params.workspace_name.as_deref(), + params.workspace_icon.as_deref(), ) .await?; Ok(AppResponse::Ok().into()) diff --git a/src/biz/workspace/ops.rs b/src/biz/workspace/ops.rs index 503da55d..98e660a1 100644 --- a/src/biz/workspace/ops.rs +++ b/src/biz/workspace/ops.rs @@ -4,7 +4,7 @@ use database::collab::upsert_collab_member_with_txn; use database::pg_row::{AFWorkspaceMemberRow, AFWorkspaceRow}; use database::user::select_uid_from_email; use database::workspace::{ - delete_from_workspace, delete_workspace_members, insert_user_workspace, + change_workspace_icon, delete_from_workspace, delete_workspace_members, insert_user_workspace, insert_workspace_member_with_txn, rename_workspace, select_all_user_workspaces, select_workspace, select_workspace_member_list, update_updated_at_of_workspace, upsert_workspace_member, }; @@ -39,11 +39,15 @@ pub async fn patch_workspace( pg_pool: &PgPool, workspace_id: &Uuid, workspace_name: Option<&str>, + workspace_icon: Option<&str>, ) -> Result<(), AppResponseError> { let mut tx = pg_pool.begin().await?; if let Some(workspace_name) = workspace_name { rename_workspace(&mut tx, workspace_id, workspace_name).await?; } + if let Some(workspace_icon) = workspace_icon { + change_workspace_icon(&mut tx, workspace_id, workspace_icon).await?; + } tx.commit().await?; Ok(()) } diff --git a/tests/workspace/workspace_crud.rs b/tests/workspace/workspace_crud.rs index 1da7c683..53495325 100644 --- a/tests/workspace/workspace_crud.rs +++ b/tests/workspace/workspace_crud.rs @@ -75,7 +75,7 @@ async fn add_and_delete_workspace_for_non_owner_user() { } #[tokio::test] -async fn test_workspace_rename() { +async fn test_workspace_rename_and_icon_change() { let (c, _user) = generate_unique_registered_user_client().await; let workspace_id = c .get_workspaces() @@ -91,6 +91,7 @@ async fn test_workspace_rename() { c.patch_workspace(PatchWorkspaceParam { workspace_id, workspace_name: Some(desired_new_name.to_string()), + ..Default::default() }) .await .expect("Failed to rename workspace"); @@ -108,6 +109,7 @@ async fn test_workspace_rename() { c.patch_workspace(PatchWorkspaceParam { workspace_id, workspace_name: None, + ..Default::default() }) .await .expect("Failed to rename workspace"); @@ -119,4 +121,32 @@ async fn test_workspace_rename() { .workspace_name; assert_eq!(actual_new_name, desired_new_name); } + { + c.patch_workspace(PatchWorkspaceParam { + workspace_id, + workspace_icon: Some("icon123".to_string()), + ..Default::default() + }) + .await + .expect("Failed to change icon"); + let workspaces = c.get_workspaces().await.expect("Failed to get workspaces"); + let icon = &workspaces.0.first().expect("No workspace found").icon; + assert_eq!(icon, "icon123"); + } + { + c.patch_workspace(PatchWorkspaceParam { + workspace_id, + workspace_name: Some("new_name456".to_string()), + workspace_icon: Some("new_icon456".to_string()), + }) + .await + .expect("Failed to change icon"); + let workspaces = c.get_workspaces().await.expect("Failed to get workspaces"); + let workspace = workspaces.0.first().expect("No workspace found"); + + let icon = workspace.icon.as_str(); + let name = workspace.workspace_name.as_str(); + assert_eq!(icon, "new_icon456"); + assert_eq!(name, "new_name456"); + } }