Skip to content

Commit

Permalink
fix: auto patch workspace folder without space (#1107)
Browse files Browse the repository at this point in the history
  • Loading branch information
khorshuheng authored Jan 3, 2025
1 parent 424796e commit a61a5c5
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 28 deletions.
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,13 @@ lto = false
[patch.crates-io]
# It's diffcult to resovle different version with the same crate used in AppFlowy Frontend and the Client-API crate.
# So using patch to workaround this issue.
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c45a2120361f94bbedb787cdd2192a38c94c7f5f" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c45a2120361f94bbedb787cdd2192a38c94c7f5f" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c45a2120361f94bbedb787cdd2192a38c94c7f5f" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c45a2120361f94bbedb787cdd2192a38c94c7f5f" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c45a2120361f94bbedb787cdd2192a38c94c7f5f" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c45a2120361f94bbedb787cdd2192a38c94c7f5f" }
collab-importer = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "c45a2120361f94bbedb787cdd2192a38c94c7f5f" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d51fecb64762855f9e54648c78ab1ee0d5404f97" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d51fecb64762855f9e54648c78ab1ee0d5404f97" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d51fecb64762855f9e54648c78ab1ee0d5404f97" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d51fecb64762855f9e54648c78ab1ee0d5404f97" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d51fecb64762855f9e54648c78ab1ee0d5404f97" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d51fecb64762855f9e54648c78ab1ee0d5404f97" }
collab-importer = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "d51fecb64762855f9e54648c78ab1ee0d5404f97" }

[features]
history = []
Expand Down
7 changes: 6 additions & 1 deletion src/api/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2024,10 +2024,13 @@ async fn get_workspace_folder_handler(
user_uuid: UserUuid,
workspace_id: web::Path<Uuid>,
state: Data<AppState>,
server: Data<RealtimeServerAddr>,
query: web::Query<QueryWorkspaceFolder>,
req: HttpRequest,
) -> Result<Json<AppResponse<FolderView>>> {
let depth = query.depth.unwrap_or(1);
let uid = state.user_cache.get_user_uid(&user_uuid).await?;
let user = realtime_user_for_web_request(req.headers(), uid)?;
let workspace_id = workspace_id.into_inner();
state
.workspace_access_control
Expand All @@ -2039,9 +2042,11 @@ async fn get_workspace_folder_handler(
workspace_id.to_string()
};
let folder_view = biz::collab::ops::get_user_workspace_structure(
&state.metrics.appflowy_web_metrics,
server,
&state.collab_access_control_storage,
&state.pg_pool,
uid,
user,
workspace_id,
depth,
&root_view_id,
Expand Down
4 changes: 1 addition & 3 deletions src/biz/collab/folder_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ use std::collections::HashSet;

use app_error::AppError;
use chrono::DateTime;
use collab_folder::{
hierarchy_builder::SpacePermission, Folder, SectionItem, ViewLayout as CollabFolderViewLayout,
};
use collab_folder::{Folder, SectionItem, SpacePermission, ViewLayout as CollabFolderViewLayout};
use shared_entity::dto::workspace_dto::{
self, FavoriteFolderView, FolderView, FolderViewMinimal, RecentFolderView, TrashFolderView,
ViewLayout,
Expand Down
105 changes: 102 additions & 3 deletions src/biz/collab/ops.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::sync::Arc;

use actix_web::web::Data;
use app_error::AppError;
use appflowy_collaborate::collab::storage::CollabAccessControlStorage;
use chrono::DateTime;
Expand All @@ -24,8 +25,12 @@ use collab_database::workspace_database::WorkspaceDatabaseBody;
use collab_document::document::Document;
use collab_entity::CollabType;
use collab_entity::EncodedCollab;
use collab_folder::hierarchy_builder::NestedChildViewBuilder;
use collab_folder::CollabOrigin;
use collab_folder::Folder;
use collab_folder::SectionItem;
use collab_folder::SpaceInfo;
use collab_rt_entity::user::RealtimeUser;
use database::collab::select_last_updated_database_row_ids;
use database::collab::select_workspace_database_oid;
use database::collab::{CollabStorage, GetCollabOrigin};
Expand All @@ -48,8 +53,12 @@ use sqlx::PgPool;
use std::ops::DerefMut;
use yrs::Map;

use crate::api::metrics::AppFlowyWebMetrics;
use crate::api::ws::RealtimeServerAddr;
use crate::biz::collab::folder_view::check_if_view_is_space;
use crate::biz::collab::utils::get_database_row_doc_changes;
use crate::biz::workspace::ops::broadcast_update_with_timeout;
use crate::biz::workspace::page_view::update_workspace_folder_data;
use access_control::collab::CollabAccessControl;
use anyhow::Context;
use database_entity::dto::{
Expand Down Expand Up @@ -82,6 +91,8 @@ use super::utils::type_options_serde;
use super::utils::write_to_database_row;
use super::utils::CreatedRowDocument;
use super::utils::DocChanges;
use super::utils::DEFAULT_SPACE_ICON;
use super::utils::DEFAULT_SPACE_ICON_COLOR;

/// Create a new collab member
/// If the collab member already exists, return [AppError::RecordAlreadyExists]
Expand Down Expand Up @@ -293,10 +304,95 @@ pub async fn get_user_trash_folder_views(
Ok(section_items_to_trash_folder_view(&section_items, &folder))
}

#[allow(clippy::too_many_arguments)]
fn patch_old_workspace_folder(
user: RealtimeUser,
workspace_id: &str,
folder: &mut Folder,
child_view_id_without_space: &[String],
) -> Result<Vec<u8>, AppError> {
let encoded_update = {
let space_id = Uuid::new_v4().to_string();

let space_view = NestedChildViewBuilder::new(user.uid, workspace_id.to_string())
.with_view_id(space_id.clone())
.with_name("General")
.with_extra(|extra| {
extra
.with_space_info(SpaceInfo {
space_icon: Some(DEFAULT_SPACE_ICON.to_string()),
space_icon_color: Some(DEFAULT_SPACE_ICON_COLOR.to_string()),
..Default::default()
})
.build()
})
.build()
.view;
let mut txn = folder.collab.transact_mut();
folder.body.views.insert(&mut txn, space_view, None);
for (i, current_view_id) in child_view_id_without_space.iter().enumerate() {
let previous_view_id = if i == 0 {
None
} else {
Some(child_view_id_without_space[i - 1].clone())
};
folder
.body
.move_nested_view(&mut txn, current_view_id, &space_id, previous_view_id);
}
txn.encode_update_v1()
};
Ok(encoded_update)
}

async fn fix_old_workspace_folder(
appflowy_web_metrics: &AppFlowyWebMetrics,
server: Data<RealtimeServerAddr>,
user: RealtimeUser,
mut folder: Folder,
workspace_id: Uuid,
) -> Result<Folder, AppError> {
let root_view = folder.get_view(&workspace_id.to_string()).ok_or_else(|| {
AppError::InvalidRequest(format!(
"Failed to get view for workspace_id: {}",
workspace_id
))
})?;
let direct_workspace_children: Vec<String> = root_view
.children
.iter()
.map(|view_id| view_id.to_string())
.collect();
let has_at_least_one_space = direct_workspace_children
.iter()
.filter_map(|view_id| folder.get_view(view_id))
.any(|view| check_if_view_is_space(&view));
if !has_at_least_one_space {
let folder_update = patch_old_workspace_folder(
user.clone(),
&workspace_id.to_string(),
&mut folder,
&direct_workspace_children,
)?;
update_workspace_folder_data(
appflowy_web_metrics,
server,
user,
workspace_id,
folder_update,
)
.await?;
}
Ok(folder)
}

#[allow(clippy::too_many_arguments)]
pub async fn get_user_workspace_structure(
appflowy_web_metrics: &AppFlowyWebMetrics,
server: Data<RealtimeServerAddr>,
collab_storage: &CollabAccessControlStorage,
pg_pool: &PgPool,
uid: i64,
user: RealtimeUser,
workspace_id: Uuid,
depth: u32,
root_view_id: &str,
Expand All @@ -310,10 +406,13 @@ pub async fn get_user_workspace_structure(
}
let folder = get_latest_collab_folder(
collab_storage,
GetCollabOrigin::User { uid },
GetCollabOrigin::User { uid: user.uid },
&workspace_id.to_string(),
)
.await?;
let patched_folder =
fix_old_workspace_folder(appflowy_web_metrics, server, user, folder, workspace_id).await?;

let publish_view_ids = select_published_view_ids_for_workspace(pg_pool, workspace_id).await?;
let publish_view_ids: HashSet<String> = publish_view_ids
.into_iter()
Expand All @@ -322,7 +421,7 @@ pub async fn get_user_workspace_structure(
collab_folder_to_folder_view(
workspace_id,
root_view_id,
&folder,
&patched_folder,
depth,
&publish_view_ids,
)
Expand Down
3 changes: 3 additions & 0 deletions src/biz/collab/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ use std::collections::HashSet;
use std::sync::Arc;
use yrs::Map;

pub const DEFAULT_SPACE_ICON: &str = "interface_essential/home-3";
pub const DEFAULT_SPACE_ICON_COLOR: &str = "0xFFA34AFD";

pub fn get_row_details_serde(
row_detail: RowDetail,
field_by_id_name_uniq: &HashMap<String, Field>,
Expand Down
16 changes: 9 additions & 7 deletions src/biz/workspace/page_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use collab_document::document::Document;
use collab_document::document_data::default_document_data;
use collab_entity::{CollabType, EncodedCollab};
use collab_folder::hierarchy_builder::NestedChildViewBuilder;
use collab_folder::{timestamp, CollabOrigin, Folder};
use collab_folder::{timestamp, CollabOrigin, Folder, SpaceInfo};
use collab_rt_entity::user::RealtimeUser;
use database::collab::{select_workspace_database_oid, CollabStorage, GetCollabOrigin};
use database::publish::select_published_view_ids_for_workspace;
Expand Down Expand Up @@ -419,12 +419,14 @@ async fn add_new_space_to_folder(
.with_view_id(view_id)
.with_name(name)
.with_extra(|builder| {
let mut extra = builder
.is_space(true, to_space_permission(space_permission))
.build();
extra["space_icon_color"] = json!(space_icon_color);
extra["space_icon"] = json!(space_icon);
extra
builder
.with_space_info(SpaceInfo {
space_icon: Some(space_icon.to_string()),
space_icon_color: Some(space_icon_color.to_string()),
space_permission: to_space_permission(space_permission),
..Default::default()
})
.build()
})
.build()
.view;
Expand Down

0 comments on commit a61a5c5

Please sign in to comment.