feat: cloud storage test (#2663)

* chore: show default user name

* chore: update

* feat: change collab storage type after auth type changed

* chore: reload folder

* chore: initial the group controller if need

* chore: update patch

* chore: update patch ref
This commit is contained in:
Nathan.fooo
2023-05-31 17:42:14 +08:00
committed by GitHub
parent 09d61c79c9
commit 012b6c0066
27 changed files with 398 additions and 285 deletions

View File

@ -6,7 +6,7 @@ use appflowy_integrate::collab_builder::AppFlowyCollabBuilder;
use appflowy_integrate::{CollabPersistenceConfig, RocksCollabDB};
use collab::core::collab::MutexCollab;
use collab_database::database::DatabaseData;
use collab_database::user::{UserDatabase as InnerUserDatabase, UserDatabaseCollabBuilder};
use collab_database::user::{DatabaseCollabBuilder, UserDatabase as InnerUserDatabase};
use collab_database::views::{CreateDatabaseParams, CreateViewParams};
use parking_lot::Mutex;
use tokio::sync::RwLock;
@ -183,7 +183,7 @@ impl DatabaseManager2 {
match duplicated_view_id {
None => {
let params = CreateViewParams::new(database_id, target_view_id, name, layout.into());
database.create_linked_view(params);
database.create_linked_view(params)?;
},
Some(duplicated_view_id) => {
database.duplicate_linked_view(&duplicated_view_id);
@ -256,18 +256,27 @@ unsafe impl Send for UserDatabase {}
struct UserDatabaseCollabBuilderImpl(Arc<AppFlowyCollabBuilder>);
impl UserDatabaseCollabBuilder for UserDatabaseCollabBuilderImpl {
fn build(&self, uid: i64, object_id: &str, db: Arc<RocksCollabDB>) -> Arc<MutexCollab> {
self.0.build(uid, object_id, db)
impl DatabaseCollabBuilder for UserDatabaseCollabBuilderImpl {
fn build(
&self,
uid: i64,
object_id: &str,
object_name: &str,
db: Arc<RocksCollabDB>,
) -> Arc<MutexCollab> {
self.0.build(uid, object_id, object_name, db)
}
fn build_with_config(
&self,
uid: i64,
object_id: &str,
object_name: &str,
db: Arc<RocksCollabDB>,
config: &CollabPersistenceConfig,
) -> Arc<MutexCollab> {
self.0.build_with_config(uid, object_id, db, config)
self
.0
.build_with_config(uid, object_id, object_name, db, config)
}
}

View File

@ -313,7 +313,7 @@ impl<'a> CellBuilder<'a> {
/// Build list of Cells from HashMap of cell string by field id.
pub fn with_cells(cell_by_field_id: HashMap<String, String>, fields: &'a [Field]) -> Self {
let field_maps = fields
.into_iter()
.iter()
.map(|field| (field.id.clone(), field))
.collect::<HashMap<String, &Field>>();

View File

@ -574,9 +574,14 @@ impl DatabaseEditor {
row_id: RowId,
options: Vec<SelectOptionPB>,
) -> FlowyResult<()> {
let field = self.database.lock().fields.get_field(field_id).ok_or(
FlowyError::record_not_found().context(format!("Field with id:{} not found", &field_id)),
)?;
let field = self
.database
.lock()
.fields
.get_field(field_id)
.ok_or_else(|| {
FlowyError::record_not_found().context(format!("Field with id:{} not found", &field_id))
})?;
debug_assert!(FieldType::from(field.field_type).is_select_option());
let mut type_option = select_type_option_from_field(&field)?;
@ -670,9 +675,14 @@ impl DatabaseEditor {
field_id: &str,
changeset: ChecklistCellChangeset,
) -> FlowyResult<()> {
let field = self.database.lock().fields.get_field(field_id).ok_or(
FlowyError::record_not_found().context(format!("Field with id:{} not found", &field_id)),
)?;
let field = self
.database
.lock()
.fields
.get_field(field_id)
.ok_or_else(|| {
FlowyError::record_not_found().context(format!("Field with id:{} not found", &field_id))
})?;
debug_assert!(FieldType::from(field.field_type).is_checklist());
self
@ -684,7 +694,7 @@ impl DatabaseEditor {
#[tracing::instrument(level = "trace", skip_all, err)]
pub async fn load_groups(&self, view_id: &str) -> FlowyResult<RepeatedGroupPB> {
let view = self.database_views.get_view_editor(view_id).await?;
let groups = view.v_load_groups().await?;
let groups = view.v_load_groups().await.unwrap_or_default();
Ok(RepeatedGroupPB { items: groups })
}

View File

@ -112,7 +112,7 @@ pub trait DatabaseViewData: Send + Sync + 'static {
pub struct DatabaseViewEditor {
pub view_id: String,
delegate: Arc<dyn DatabaseViewData>,
group_controller: Arc<RwLock<Box<dyn GroupController>>>,
group_controller: Arc<RwLock<Option<Box<dyn GroupController>>>>,
filter_controller: Arc<FilterController>,
sort_controller: Arc<RwLock<SortController>>,
pub notifier: DatabaseViewChangedNotifier,
@ -192,10 +192,12 @@ impl DatabaseViewEditor {
},
Some(group_id) => {
self
.group_controller
.write()
.await
.did_create_row(row, group_id);
.mut_group_controller(|group_controller, _| {
group_controller.did_create_row(row, group_id);
Ok(())
})
.await;
let inserted_row = InsertedRowPB {
row: RowPB::from(row),
index: Some(index as i32),
@ -347,22 +349,29 @@ impl DatabaseViewEditor {
}
/// Only call once after database view editor initialized
#[tracing::instrument(level = "trace", skip(self))]
pub async fn v_load_groups(&self) -> FlowyResult<Vec<GroupPB>> {
pub async fn v_load_groups(&self) -> Option<Vec<GroupPB>> {
let groups = self
.group_controller
.read()
.await
.as_ref()?
.groups()
.into_iter()
.map(|group_data| GroupPB::from(group_data.clone()))
.collect::<Vec<_>>();
tracing::trace!("Number of groups: {}", groups.len());
Ok(groups)
Some(groups)
}
#[tracing::instrument(level = "trace", skip(self))]
pub async fn v_get_group(&self, group_id: &str) -> FlowyResult<GroupPB> {
match self.group_controller.read().await.get_group(group_id) {
match self
.group_controller
.read()
.await
.as_ref()
.and_then(|group| group.get_group(group_id))
{
None => Err(FlowyError::record_not_found().context("Can't find the group")),
Some((_, group)) => Ok(GroupPB::from(group)),
}
@ -371,19 +380,22 @@ impl DatabaseViewEditor {
#[tracing::instrument(level = "trace", skip(self), err)]
pub async fn v_move_group(&self, from_group: &str, to_group: &str) -> FlowyResult<()> {
self
.group_controller
.write()
.await
.move_group(from_group, to_group)?;
.mut_group_controller(|group_controller, _| group_controller.move_group(from_group, to_group))
.await;
Ok(())
}
pub async fn group_id(&self) -> String {
self.group_controller.read().await.field_id().to_string()
pub async fn is_grouping_field(&self, field_id: &str) -> bool {
match self.group_controller.read().await.as_ref() {
Some(group_controller) => group_controller.field_id() == field_id,
None => false,
}
}
/// Called when the user changes the grouping field
pub async fn v_initialize_new_group(&self, field_id: &str) -> FlowyResult<()> {
if self.group_controller.read().await.field_id() != field_id {
let is_grouping_field = self.is_grouping_field(field_id).await;
if !is_grouping_field {
self.v_update_grouping_field(field_id).await?;
if let Some(view) = self.delegate.get_view_setting(&self.view_id).await {
@ -400,10 +412,11 @@ impl DatabaseViewEditor {
pub async fn update_group_setting(&self, changeset: GroupSettingChangeset) -> FlowyResult<()> {
self
.group_controller
.write()
.await
.apply_group_setting_changeset(changeset)
.mut_group_controller(|group_controller, _| {
group_controller.apply_group_setting_changeset(changeset)
})
.await;
Ok(())
}
pub async fn v_get_all_sorts(&self) -> Vec<Sort> {
@ -631,10 +644,11 @@ impl DatabaseViewEditor {
.await;
self
.group_controller
.write()
.await
.did_update_field_type_option(&field);
.mut_group_controller(|group_controller, _| {
group_controller.did_update_field_type_option(&field);
Ok(())
})
.await;
if let Some(filter) = self
.delegate
@ -672,7 +686,7 @@ impl DatabaseViewEditor {
.map(|group| GroupPB::from(group.clone()))
.collect();
*self.group_controller.write().await = new_group_controller;
*self.group_controller.write().await = Some(new_group_controller);
let changeset = GroupChangesPB {
view_id: self.view_id.clone(),
initial_groups: new_groups,
@ -804,13 +818,19 @@ impl DatabaseViewEditor {
where
F: FnOnce(&mut Box<dyn GroupController>, Arc<Field>) -> FlowyResult<T>,
{
let group_field_id = self.group_controller.read().await.field_id().to_owned();
match self.delegate.get_field(&group_field_id).await {
None => None,
Some(field) => {
let mut write_guard = self.group_controller.write().await;
f(&mut write_guard, field).ok()
},
let group_field_id = self
.group_controller
.read()
.await
.as_ref()
.map(|group| group.field_id().to_owned())?;
let field = self.delegate.get_field(&group_field_id).await?;
let mut write_guard = self.group_controller.write().await;
if let Some(group_controller) = &mut *write_guard {
f(group_controller, field).ok()
} else {
None
}
}
}

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use collab_database::fields::Field;
use collab_database::rows::RowId;
use flowy_error::{FlowyError, FlowyResult};
use flowy_error::FlowyResult;
use lib_infra::future::{to_fut, Fut};
use crate::entities::FieldType;
@ -35,13 +35,9 @@ pub async fn new_group_controller_with_field(
pub async fn new_group_controller(
view_id: String,
delegate: Arc<dyn DatabaseViewData>,
) -> FlowyResult<Box<dyn GroupController>> {
let setting_reader = GroupSettingReaderImpl(delegate.clone());
let setting_writer = GroupSettingWriterImpl(delegate.clone());
) -> FlowyResult<Option<Box<dyn GroupController>>> {
let fields = delegate.get_fields(&view_id, None).await;
let rows = delegate.get_rows(&view_id).await;
let layout = delegate.get_layout_for_view(&view_id);
let setting_reader = GroupSettingReaderImpl(delegate.clone());
// Read the grouping field or find a new grouping field
let mut grouping_field = setting_reader
@ -54,22 +50,29 @@ pub async fn new_group_controller(
.cloned()
});
if grouping_field.is_none() {
grouping_field = find_new_grouping_field(&fields, &layout);
let layout = delegate.get_layout_for_view(&view_id);
// If the view is a board and the grouping field is empty, we need to find a new grouping field
if layout.is_board() {
if grouping_field.is_none() {
grouping_field = find_new_grouping_field(&fields, &layout);
}
}
match grouping_field {
None => Err(FlowyError::internal().context("No grouping field found".to_owned())),
Some(_) => {
if let Some(grouping_field) = grouping_field {
let rows = delegate.get_rows(&view_id).await;
let setting_writer = GroupSettingWriterImpl(delegate.clone());
Ok(Some(
make_group_controller(
view_id,
grouping_field.unwrap(),
grouping_field,
rows,
setting_reader,
setting_writer,
)
.await
},
.await?,
))
} else {
Ok(None)
}
}

View File

@ -93,7 +93,7 @@ impl DatabaseViews {
let view_editor = self.get_view_editor(view_id).await?;
// If the id of the grouping field is equal to the updated field's id, then we need to
// update the group setting
if view_editor.group_id().await == field_id {
if view_editor.is_grouping_field(field_id).await {
view_editor.v_update_grouping_field(field_id).await?;
}
view_editor

View File

@ -108,7 +108,7 @@ fn update_cell_data_with_changeset(
.into_iter()
.for_each(|option_name| {
let option = SelectOption::new(&option_name);
cell_data.options.push(option.clone());
cell_data.options.push(option);
});
// Update options

View File

@ -134,7 +134,7 @@ async fn update_updated_at_field_on_other_cell_update() {
.editor
.get_cells_for_field(&test.view_id, &updated_at_field.id)
.await;
assert!(cells.len() > 0);
assert!(!cells.is_empty());
for (i, cell) in cells.into_iter().enumerate() {
let timestamp = DateCellData::from(cell.as_ref()).timestamp.unwrap();
println!(

View File

@ -11,7 +11,7 @@ async fn export_meta_csv_test() {
let database = test.editor.clone();
let s = database.export_csv(CSVFormat::META).await.unwrap();
let mut reader = csv::Reader::from_reader(s.as_bytes());
for header in reader.headers() {
for header in reader.headers().unwrap() {
dbg!(header);
}