From 27cb3d01d520b205b7043c5a6e349d48162ec0e3 Mon Sep 17 00:00:00 2001 From: "Kilu.He" <108015703+qinluhe@users.noreply.github.com> Date: Tue, 21 May 2024 10:08:09 +0800 Subject: [PATCH] feat: add get user workspace (#526) * feat: add get user workspace * feat: support batch get collab * fix: decode batch collab * fix: modified the method of batch_get_collab to post * fix: modified a private function for batch collab * fix: warning --- libs/client-api-wasm/src/entities.rs | 111 ++++++++++++++++++++++++++- libs/client-api-wasm/src/lib.rs | 22 ++++++ libs/client-api/src/http.rs | 26 ++++++- 3 files changed, 156 insertions(+), 3 deletions(-) diff --git a/libs/client-api-wasm/src/entities.rs b/libs/client-api-wasm/src/entities.rs index 5adfa280..ce1000bc 100644 --- a/libs/client-api-wasm/src/entities.rs +++ b/libs/client-api-wasm/src/entities.rs @@ -1,9 +1,13 @@ use client_api::entity::AFUserProfile; use client_api::error::{AppResponseError, ErrorCode}; use collab_entity::{CollabType, EncodedCollab}; -use database_entity::dto::{QueryCollab, QueryCollabParams}; +use database_entity::dto::{ + AFUserWorkspaceInfo, AFWorkspace, BatchQueryCollabResult, QueryCollab, QueryCollabParams, + QueryCollabResult, +}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; +use std::collections::HashMap; use tsify::Tsify; use wasm_bindgen::JsValue; @@ -83,6 +87,60 @@ impl From for User { } } +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct UserWorkspace { + pub user: User, + pub visiting_workspace_id: String, + pub workspaces: Vec, +} + +from_struct_for_jsvalue!(UserWorkspace); + +impl From for UserWorkspace { + fn from(info: AFUserWorkspaceInfo) -> Self { + UserWorkspace { + user: User::from(info.user_profile), + visiting_workspace_id: info.visiting_workspace.workspace_id.to_string(), + workspaces: info + .workspaces + .into_iter() + .map(|workspace| Workspace::from(workspace)) + .collect(), + } + } +} + +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct Workspace { + pub workspace_id: String, + pub database_storage_id: String, + pub owner_uid: String, + pub owner_name: String, + pub workspace_type: i32, + pub workspace_name: String, + pub created_at: String, + pub icon: String, +} + +from_struct_for_jsvalue!(Workspace); + +impl From for Workspace { + fn from(workspace: AFWorkspace) -> Self { + Workspace { + workspace_id: workspace.workspace_id.to_string(), + database_storage_id: workspace.database_storage_id.to_string(), + owner_uid: workspace.owner_uid.to_string(), + owner_name: workspace.owner_name, + workspace_type: workspace.workspace_type as i32, + workspace_name: workspace.workspace_name, + created_at: workspace.created_at.timestamp().to_string(), + icon: workspace.icon, + } + } +} + #[derive(Tsify, Serialize, Deserialize, Default, Debug)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct ClientQueryCollabParams { @@ -132,3 +190,54 @@ impl From for ClientEncodeCollab { } } } + +#[derive(Tsify, Serialize, Deserialize, Default, Debug)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct BatchClientQueryCollab(pub Vec); +#[derive(Tsify, Serialize, Deserialize, Default, Debug)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct ClientQueryCollab { + pub object_id: String, + #[tsify(type = "0 | 1 | 2 | 3 | 4 | 5")] + pub collab_type: i32, +} + +from_struct_for_jsvalue!(ClientQueryCollab); + +impl From for QueryCollab { + fn from(value: ClientQueryCollab) -> QueryCollab { + QueryCollab { + collab_type: CollabType::from(value.collab_type), + object_id: value.object_id, + } + } +} + +#[derive(Tsify, Serialize, Deserialize, Default)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct BatchClientEncodeCollab(pub HashMap); + +from_struct_for_jsvalue!(BatchClientEncodeCollab); + +impl From for BatchClientEncodeCollab { + fn from(result: BatchQueryCollabResult) -> Self { + let mut hash_map = HashMap::new(); + + result.0.into_iter().for_each(|(k, v)| match v { + QueryCollabResult::Success { encode_collab_v1 } => { + EncodedCollab::decode_from_bytes(&encode_collab_v1) + .map(|collab| { + hash_map.insert(k, ClientEncodeCollab::from(collab)); + }) + .unwrap_or_else(|err| { + tracing::error!("Failed to decode collab: {:?}", err); + }); + }, + QueryCollabResult::Failed { .. } => { + tracing::error!("Failed to get collab: {:?}", k); + }, + }); + + BatchClientEncodeCollab(hash_map) + } +} diff --git a/libs/client-api-wasm/src/lib.rs b/libs/client-api-wasm/src/lib.rs index 40c01afe..09bc584f 100644 --- a/libs/client-api-wasm/src/lib.rs +++ b/libs/client-api-wasm/src/lib.rs @@ -6,6 +6,7 @@ use client_api::notify::TokenState; use client_api::{Client, ClientConfiguration}; use std::sync::Arc; +use database_entity::dto::QueryCollab; use wasm_bindgen::prelude::*; #[cfg(feature = "enable_wee_alloc")] @@ -138,4 +139,25 @@ impl ClientAPI { Err(err) => Err(ClientResponse::from(err)), } } + + pub async fn batch_get_collab( + &self, + workspace_id: String, + params: BatchClientQueryCollab, + ) -> Result { + tracing::debug!("batch_get_collab: {:?}", params); + let workspace_id = workspace_id.as_str(); + let params: Vec = params.0.into_iter().map(|p| p.into()).collect(); + match self.client.batch_post_collab(workspace_id, params).await { + Ok(data) => Ok(BatchClientEncodeCollab::from(data)), + Err(err) => Err(ClientResponse::from(err)), + } + } + + pub async fn get_user_workspace(&self) -> Result { + match self.client.get_user_workspace_info().await { + Ok(workspace_info) => Ok(UserWorkspace::from(workspace_info)), + Err(err) => Err(ClientResponse::from(err)), + } + } } diff --git a/libs/client-api/src/http.rs b/libs/client-api/src/http.rs index 37bed9f4..8cdc813d 100644 --- a/libs/client-api/src/http.rs +++ b/libs/client-api/src/http.rs @@ -965,11 +965,34 @@ impl Client { AppResponse::<()>::from_response(resp).await?.into_error() } + // The browser will call this API to get the collab list, because the URL length limit and browser can't send the body in GET request + #[instrument(level = "info", skip_all, err)] + pub async fn batch_post_collab( + &self, + workspace_id: &str, + params: Vec, + ) -> Result { + self + .send_batch_collab_request(Method::POST, workspace_id, params) + .await + } + #[instrument(level = "info", skip_all, err)] pub async fn batch_get_collab( &self, workspace_id: &str, params: Vec, + ) -> Result { + self + .send_batch_collab_request(Method::GET, workspace_id, params) + .await + } + + async fn send_batch_collab_request( + &self, + method: Method, + workspace_id: &str, + params: Vec, ) -> Result { let url = format!( "{}/api/workspace/{}/collab_list", @@ -977,7 +1000,7 @@ impl Client { ); let params = BatchQueryCollabParams(params); let resp = self - .http_client_with_auth(Method::GET, &url) + .http_client_with_auth(method, &url) .await? .json(¶ms) .send() @@ -987,7 +1010,6 @@ impl Client { .await? .into_data() } - #[instrument(level = "info", skip_all, err)] pub async fn delete_collab(&self, params: DeleteCollabParams) -> Result<(), AppResponseError> { let url = format!(