chore: merge with upstream

This commit is contained in:
Zack Fu Zi Xiang 2024-09-10 19:41:14 +08:00
commit 1cf858aab7
No known key found for this signature in database
3 changed files with 78 additions and 109 deletions

View File

@ -218,7 +218,7 @@ impl TestClient {
pub async fn get_db_collab_from_view(&mut self, workspace_id: &str, view_id: &str) -> Collab { pub async fn get_db_collab_from_view(&mut self, workspace_id: &str, view_id: &str) -> Collab {
let mut ws_db_collab = self.get_workspace_database_collab(workspace_id).await; let mut ws_db_collab = self.get_workspace_database_collab(workspace_id).await;
let ws_db_body = WorkspaceDatabaseBody::new(&mut ws_db_collab); let ws_db_body = WorkspaceDatabaseBody::open(&mut ws_db_collab);
let txn = ws_db_collab.transact(); let txn = ws_db_collab.transact();
let db_id = ws_db_body let db_id = ws_db_body
.get_all_database_meta(&txn) .get_all_database_meta(&txn)
@ -236,11 +236,10 @@ impl TestClient {
}) })
.await .await
.unwrap(); .unwrap();
let db_doc_state = db_collab_collab_resp.encode_collab.doc_state;
Collab::new_with_source( Collab::new_with_source(
CollabOrigin::Server, CollabOrigin::Server,
&db_id, &db_id,
DataSource::DocStateV1(db_doc_state.to_vec()), db_collab_collab_resp.encode_collab.into(),
vec![], vec![],
false, false,
) )

View File

@ -4,10 +4,10 @@ use collab::core::collab::DataSource;
use collab::preclude::Collab; use collab::preclude::Collab;
use collab::preclude::MapExt; use collab::preclude::MapExt;
use collab_database::database::DatabaseBody;
use collab_database::entity::FieldType; use collab_database::entity::FieldType;
use collab_database::rows::meta_id_from_row_id; use collab_database::rows::meta_id_from_row_id;
use collab_database::rows::RowMetaKey; use collab_database::rows::RowMetaKey;
use collab_database::views::DatabaseViews;
use collab_database::workspace_database::WorkspaceDatabaseBody; use collab_database::workspace_database::WorkspaceDatabaseBody;
use collab_document::blocks::DocumentData; use collab_document::blocks::DocumentData;
use collab_document::document::Document; use collab_document::document::Document;
@ -673,7 +673,9 @@ impl PublishCollabDuplicator {
) -> Result<(String, String, bool), AppError> { ) -> Result<(String, String, bool), AppError> {
// collab of database // collab of database
let mut db_collab = collab_from_doc_state(published_db.database_collab.clone(), "")?; let mut db_collab = collab_from_doc_state(published_db.database_collab.clone(), "")?;
let pub_db_id = get_database_id_from_collab(&db_collab)?; let db_body = DatabaseBody::from_collab(&db_collab)
.ok_or_else(|| AppError::RecordNotFound("no database body found".to_string()))?;
let pub_db_id = db_body.get_database_id(&db_collab.context.transact());
// check if the database is already duplicated // check if the database is already duplicated
if let Some(db_id) = self.duplicated_refs.get(&pub_db_id).cloned().flatten() { if let Some(db_id) = self.duplicated_refs.get(&pub_db_id).cloned().flatten() {
@ -686,44 +688,39 @@ impl PublishCollabDuplicator {
{ {
// handle row relations // handle row relations
// collect all map ref with `database_id` fields
// deep copy those database
let mut txn = db_collab.context.transact_mut(); let mut txn = db_collab.context.transact_mut();
let database_fields: MapRef = db_collab let all_fields = db_body.fields.get_all_fields(&txn);
.data for mut field in all_fields {
.get_with_path(&txn, ["database", "fields"]) for (key, type_option_value) in field.type_options.iter_mut() {
.ok_or_else(|| AppError::RecordNotFound("no fields found in database".to_string()))?; if *key == FieldType::Relation.type_id() {
let mut type_option_values = vec![]; if let Some(pub_db_id) = type_option_value.get_mut("database_id") {
for (_, out) in database_fields.iter(&txn) { if let any::Any::String(pub_db_id_str) = pub_db_id {
if let Ok(m1) = out.cast::<MapRef>() { if let Some(related_db_view) =
if let Some(type_option) = m1.get(&txn, "type_option") { published_db.database_relations.get(pub_db_id_str.as_ref())
if let Ok(m2) = type_option.cast::<MapRef>() { {
for (_, out2) in m2.iter(&txn) { if let Some(_dup_view_id) = self
if let Ok(m3) = out2.cast::<MapRef>() { .deep_copy_view(related_db_view, &self.dest_view_id.to_string())
type_option_values.push(m3); .await?
} {
if let Some(dup_db_id) = self
.duplicated_refs
.get(pub_db_id_str.as_ref())
.cloned()
.flatten()
{
*pub_db_id = any::Any::String(dup_db_id.into());
db_body.fields.update_field(&mut txn, &field.id, |f| {
f.set_type_option(
FieldType::Relation.into(),
Some(type_option_value.clone()),
);
});
};
};
};
} }
}
}
}
}
for m in type_option_values {
if let Some(Out::Any(any::Any::String(pub_db_id))) = m.get(&txn, "database_id") {
if let Some(related_db_view) = published_db.database_relations.get(pub_db_id.as_ref()) {
if let Some(_dup_view_id) = self
.deep_copy_view(related_db_view, &self.dest_view_id.to_string())
.await?
{
if let Some(dup_db_id) = self
.duplicated_refs
.get(pub_db_id.as_ref())
.cloned()
.flatten()
{
m.insert(&mut txn, "database_id", dup_db_id.as_str());
};
}; };
}; }
} }
} }
} }
@ -750,6 +747,22 @@ impl PublishCollabDuplicator {
{ {
// update relation cells // update relation cells
// db_row_collb: Object {
// "data": Object {
// "cells": Object {
// "MBaTsr": Object {
// "data": Array [
// String("eefb5700-8cf7-411e-9596-f60b9a51916e"),
// String("23d5e054-42c8-4754-ad69-527e4ffc1e46"),
// // above are published row ids of related database
// // we need to replace them with respective duplicated row ids
// ],
// "field_type": Number(10),
// // use this condition to filter out relation cells
// },
// },
// },
// }
let cells: MapRef = db_row_collab let cells: MapRef = db_row_collab
.data .data
.get_with_path(&txn, ["data", "cells"]) .get_with_path(&txn, ["data", "cells"])
@ -900,25 +913,9 @@ impl PublishCollabDuplicator {
let mut new_db_view_ids: Vec<String> = vec![]; let mut new_db_view_ids: Vec<String> = vec![];
{ {
let mut txn = db_collab.context.transact_mut(); let mut txn = db_collab.context.transact_mut();
let container = db_collab db_body.root.insert(&mut txn, "id", new_db_id.clone());
.data
.get(&txn, "database")
.ok_or_else(|| AppError::RecordNotFound("no database found in collab".to_string()))?
.cast::<MapRef>()
.map_err(|err| AppError::Unhandled(format!("not a map: {:?}", err)))?;
container.insert(&mut txn, "id", new_db_id.clone());
let view_map = {
let map_ref = db_collab
.data
.get_with_path(&txn, ["database", "views"])
.ok_or_else(|| AppError::RecordNotFound("no views found in database".to_string()))?;
DatabaseViews::new(CollabOrigin::Empty, map_ref, None)
};
// create new database views based on published views
let mut db_views = view_map.get_all_views(&txn);
let mut db_views = db_body.views.get_all_views(&txn);
for db_view in db_views.iter_mut() { for db_view in db_views.iter_mut() {
let new_db_view_id = if db_view.id == publish_view_id { let new_db_view_id = if db_view.id == publish_view_id {
self self
@ -949,16 +946,12 @@ impl PublishCollabDuplicator {
} }
// update database metas iid // update database metas iid
let metas: MapRef = db_collab db_body.metas.insert(&mut txn, "iid", new_view_id);
.data
.get_with_path(&txn, ["database", "metas"])
.ok_or_else(|| AppError::RecordNotFound("no metas found in database".to_string()))?;
metas.insert(&mut txn, "iid", new_view_id);
// insert updated views back to db // insert updated views back to db
view_map.clear(&mut txn); db_body.views.clear(&mut txn);
for view in db_views { for view in db_views {
view_map.insert_view(&mut txn, view); db_body.views.insert_view(&mut txn, view);
} }
} }
@ -1168,20 +1161,6 @@ pub fn collab_from_doc_state(doc_state: Vec<u8>, object_id: &str) -> Result<Coll
Ok(collab) Ok(collab)
} }
pub fn get_database_id_from_collab(db_collab: &Collab) -> Result<String, AppError> {
let txn = db_collab.context.transact();
let db_map = db_collab
.get_with_txn(&txn, "database")
.ok_or_else(|| AppError::RecordNotFound("no database found in database collab".to_string()))?
.cast::<MapRef>()
.map_err(|err| AppError::RecordNotFound(format!("database not a map: {:?}", err)))?;
let db_id = db_map
.get(&txn, "id")
.ok_or_else(|| AppError::RecordNotFound("no id found in database".to_string()))?
.to_string(&txn);
Ok(db_id)
}
fn to_folder_view_icon(icon: workspace_dto::ViewIcon) -> collab_folder::ViewIcon { fn to_folder_view_icon(icon: workspace_dto::ViewIcon) -> collab_folder::ViewIcon {
collab_folder::ViewIcon { collab_folder::ViewIcon {
ty: to_folder_view_icon_type(icon.ty), ty: to_folder_view_icon_type(icon.ty),

View File

@ -1,14 +1,14 @@
use app_error::ErrorCode; use app_error::ErrorCode;
use appflowy_cloud::biz::collab::folder_view::collab_folder_to_folder_view; use appflowy_cloud::biz::collab::folder_view::collab_folder_to_folder_view;
use appflowy_cloud::biz::workspace::publish_dup::{ use appflowy_cloud::biz::workspace::publish_dup::collab_from_doc_state;
collab_from_doc_state, get_database_id_from_collab,
};
use client_api::entity::{ use client_api::entity::{
AFRole, GlobalComment, PublishCollabItem, PublishCollabMetadata, QueryCollab, QueryCollabParams, AFRole, GlobalComment, PublishCollabItem, PublishCollabMetadata, QueryCollab, QueryCollabParams,
}; };
use client_api_test::TestClient; use client_api_test::TestClient;
use client_api_test::{generate_unique_registered_user_client, localhost_client}; use client_api_test::{generate_unique_registered_user_client, localhost_client};
use collab::util::MapExt; use collab::util::MapExt;
use collab_database::database::DatabaseBody;
use collab_database::entity::FieldType;
use collab_database::views::DatabaseViews; use collab_database::views::DatabaseViews;
use collab_database::workspace_database::WorkspaceDatabaseBody; use collab_database::workspace_database::WorkspaceDatabaseBody;
use collab_document::document::Document; use collab_document::document::Document;
@ -21,8 +21,6 @@ use shared_entity::dto::workspace_dto::PublishedDuplicate;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use yrs::types::Map;
use yrs::MapRef;
use crate::workspace::published_data::{self}; use crate::workspace::published_data::{self};
@ -962,7 +960,7 @@ async fn duplicate_to_workspace_doc_inline_database() {
.unwrap(); .unwrap();
let db_doc_state = db_collab_collab_resp.encode_collab.doc_state; let db_doc_state = db_collab_collab_resp.encode_collab.doc_state;
let db_collab = collab_from_doc_state(db_doc_state.to_vec(), "").unwrap(); let db_collab = collab_from_doc_state(db_doc_state.to_vec(), "").unwrap();
let dup_db_id = get_database_id_from_collab(&db_collab).unwrap(); let dup_db_id = DatabaseBody::database_id_from_collab(&db_collab).unwrap();
assert_ne!(dup_db_id, pub_db_id); assert_ne!(dup_db_id, pub_db_id);
let view_map = { let view_map = {
@ -1200,31 +1198,24 @@ async fn duplicate_to_workspace_db_with_relation() {
.get_db_collab_from_view(&workspace_id_2, &related_db.view_id) .get_db_collab_from_view(&workspace_id_2, &related_db.view_id)
.await; .await;
let fields: MapRef = db_with_rel_col_collab let related_db_id: String = related_db_collab
.data .data
.get_with_path(&db_with_rel_col_collab.transact(), ["database", "fields"]) .get_with_path(&related_db_collab.transact(), ["database", "id"])
.unwrap(); .unwrap();
for (_k, v) in fields.iter(&db_with_rel_col_collab.transact()) {
for related_col_db_id in v let rel_col_db_body = DatabaseBody::from_collab(&db_with_rel_col_collab).unwrap();
.cast::<MapRef>() let txn = db_with_rel_col_collab.transact();
.unwrap() let all_fields = rel_col_db_body.fields.get_all_fields(&txn);
.get(&db_with_rel_col_collab.transact(), "type_option") all_fields
.unwrap() .iter()
.cast::<MapRef>() .map(|f| &f.type_options)
.unwrap() .flat_map(|t| t.iter())
.iter(&db_with_rel_col_collab.transact()) .filter(|(k, _v)| **k == FieldType::Relation.type_id())
.map(|(_k, v)| v.cast::<MapRef>().unwrap()) .map(|(_k, v)| v)
.flat_map(|v| v.get(&db_with_rel_col_collab.transact(), "database_id")) .flat_map(|v| v.iter())
.map(|v| v.to_string(&db_with_rel_col_collab.transact())) .for_each(|(_k, db_id)| {
.filter(|v| !v.is_empty()) assert_eq!(db_id.to_string(), related_db_id);
{ });
let related_db_id: String = related_db_collab
.data
.get_with_path(&related_db_collab.transact(), ["database", "id"])
.unwrap();
assert_eq!(related_db_id, related_col_db_id);
}
}
} }
} }
} }
@ -1232,7 +1223,7 @@ async fn duplicate_to_workspace_db_with_relation() {
fn get_database_id_and_row_ids(published_db_blob: &[u8]) -> (String, HashSet<String>) { fn get_database_id_and_row_ids(published_db_blob: &[u8]) -> (String, HashSet<String>) {
let pub_db_data = serde_json::from_slice::<PublishDatabaseData>(published_db_blob).unwrap(); let pub_db_data = serde_json::from_slice::<PublishDatabaseData>(published_db_blob).unwrap();
let db_collab = collab_from_doc_state(pub_db_data.database_collab, "").unwrap(); let db_collab = collab_from_doc_state(pub_db_data.database_collab, "").unwrap();
let pub_db_id = get_database_id_from_collab(&db_collab).unwrap(); let pub_db_id = DatabaseBody::database_id_from_collab(&db_collab).unwrap();
let row_ids: HashSet<String> = pub_db_data.database_row_collabs.into_keys().collect(); let row_ids: HashSet<String> = pub_db_data.database_row_collabs.into_keys().collect();
(pub_db_id, row_ids) (pub_db_id, row_ids)
} }