refactor: streamline create row logic (#4807)

This commit is contained in:
Richard Shiue 2024-03-14 11:26:32 +08:00 committed by GitHub
parent 25d4b4f718
commit 191a077a86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 155 additions and 200 deletions

View File

@ -28,16 +28,10 @@ class RowBackendService {
), ),
); );
Map<String, String>? cellDataByFieldId;
if (withCells != null) { if (withCells != null) {
final rowBuilder = RowDataBuilder(); final rowBuilder = RowDataBuilder();
withCells(rowBuilder); withCells(rowBuilder);
cellDataByFieldId = rowBuilder.build(); payload.data.addAll(rowBuilder.build());
}
if (cellDataByFieldId != null) {
payload.data = RowDataPB(cellDataByFieldId: cellDataByFieldId);
} }
return DatabaseEventCreateRow(payload).send(); return DatabaseEventCreateRow(payload).send();

View File

@ -30,7 +30,7 @@ export async function createRow(viewId: string, params?: {
object_id: params?.rowId, object_id: params?.rowId,
}, },
group_id: params?.groupId, group_id: params?.groupId,
data: params?.data ? { cell_data_by_field_id: params.data } : undefined, data: params?.data,
}); });
const result = await DatabaseEventCreateRow(payload); const result = await DatabaseEventCreateRow(payload);

View File

@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use bytes::Bytes; use bytes::Bytes;
@ -200,7 +201,7 @@ impl EventIntegrationTest {
&self, &self,
view_id: &str, view_id: &str,
row_position: OrderObjectPositionPB, row_position: OrderObjectPositionPB,
data: Option<RowDataPB>, data: Option<HashMap<String, String>>,
) -> RowMetaPB { ) -> RowMetaPB {
EventBuilder::new(self.clone()) EventBuilder::new(self.clone())
.event(DatabaseEvent::CreateRow) .event(DatabaseEvent::CreateRow)
@ -208,7 +209,7 @@ impl EventIntegrationTest {
view_id: view_id.to_string(), view_id: view_id.to_string(),
row_position, row_position,
group_id: None, group_id: None,
data, data: data.unwrap_or_default(),
}) })
.async_send() .async_send()
.await .await

View File

@ -1,10 +1,12 @@
use std::collections::HashMap; use std::collections::HashMap;
use collab_database::rows::{Row, RowDetail, RowId}; use collab_database::rows::{Row, RowDetail, RowId};
use collab_database::views::{OrderObjectPosition, RowOrder}; use collab_database::views::RowOrder;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use lib_infra::validator_fn::required_not_empty_str;
use validator::Validate;
use crate::entities::parser::NotEmptyStr; use crate::entities::parser::NotEmptyStr;
use crate::entities::position_entities::OrderObjectPositionPB; use crate::entities::position_entities::OrderObjectPositionPB;
@ -335,46 +337,25 @@ impl TryInto<RowIdParams> for RowIdPB {
} }
} }
#[derive(ProtoBuf, Default)] #[derive(ProtoBuf, Default, Validate)]
pub struct CreateRowPayloadPB { pub struct CreateRowPayloadPB {
#[pb(index = 1)] #[pb(index = 1)]
#[validate(custom = "required_not_empty_str")]
pub view_id: String, pub view_id: String,
#[pb(index = 2)] #[pb(index = 2)]
pub row_position: OrderObjectPositionPB, pub row_position: OrderObjectPositionPB,
#[pb(index = 3, one_of)] #[pb(index = 3, one_of)]
#[validate(custom = "required_not_empty_str")]
pub group_id: Option<String>, pub group_id: Option<String>,
#[pb(index = 4, one_of)] #[pb(index = 4)]
pub data: Option<RowDataPB>, pub data: HashMap<String, String>,
}
#[derive(ProtoBuf, Default)]
pub struct RowDataPB {
#[pb(index = 1)]
pub cell_data_by_field_id: HashMap<String, String>,
} }
#[derive(Default)] #[derive(Default)]
pub struct CreateRowParams { pub struct CreateRowParams {
pub view_id: String, pub collab_params: collab_database::rows::CreateRowParams,
pub row_position: OrderObjectPosition, pub open_after_create: bool,
pub group_id: Option<String>,
pub cell_data_by_field_id: Option<HashMap<String, String>>,
}
impl TryInto<CreateRowParams> for CreateRowPayloadPB {
type Error = ErrorCode;
fn try_into(self) -> Result<CreateRowParams, Self::Error> {
let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::ViewIdIsInvalid)?;
let position = self.row_position.try_into()?;
Ok(CreateRowParams {
view_id: view_id.0,
row_position: position,
group_id: self.group_id,
cell_data_by_field_id: self.data.map(|data| data.cell_data_by_field_id),
})
}
} }

View File

@ -1,17 +1,14 @@
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use collab_database::database::gen_row_id;
use collab_database::rows::RowId; use collab_database::rows::RowId;
use lib_infra::box_any::BoxAny; use lib_infra::box_any::BoxAny;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use lib_dispatch::prelude::{af_spawn, data_result_ok, AFPluginData, AFPluginState, DataResult}; use lib_dispatch::prelude::{af_spawn, data_result_ok, AFPluginData, AFPluginState, DataResult};
use lib_infra::util::timestamp;
use crate::entities::*; use crate::entities::*;
use crate::manager::DatabaseManager; use crate::manager::DatabaseManager;
use crate::services::cell::CellBuilder;
use crate::services::field::{ use crate::services::field::{
type_option_data_from_pb, ChecklistCellChangeset, DateCellChangeset, RelationCellChangeset, type_option_data_from_pb, ChecklistCellChangeset, DateCellChangeset, RelationCellChangeset,
SelectOptionCellChangeset, SelectOptionCellChangeset,
@ -393,7 +390,7 @@ pub(crate) async fn duplicate_row_handler(
let database_editor = manager.get_database_with_view_id(&params.view_id).await?; let database_editor = manager.get_database_with_view_id(&params.view_id).await?;
database_editor database_editor
.duplicate_row(&params.view_id, &params.row_id) .duplicate_row(&params.view_id, &params.row_id)
.await; .await?;
Ok(()) Ok(())
} }
@ -417,27 +414,12 @@ pub(crate) async fn create_row_handler(
manager: AFPluginState<Weak<DatabaseManager>>, manager: AFPluginState<Weak<DatabaseManager>>,
) -> DataResult<RowMetaPB, FlowyError> { ) -> DataResult<RowMetaPB, FlowyError> {
let manager = upgrade_manager(manager)?; let manager = upgrade_manager(manager)?;
let params: CreateRowParams = data.into_inner().try_into()?; let params = data.try_into_inner()?;
let database_editor = manager.get_database_with_view_id(&params.view_id).await?; let database_editor = manager.get_database_with_view_id(&params.view_id).await?;
let fields = database_editor.get_fields(&params.view_id, None);
let cells = match database_editor.create_row(params).await? {
CellBuilder::with_cells(params.cell_data_by_field_id.unwrap_or_default(), &fields).build();
let view_id = params.view_id;
let group_id = params.group_id;
let params = collab_database::rows::CreateRowParams {
id: gen_row_id(),
cells,
height: 60,
visibility: true,
row_position: params.row_position,
timestamp: timestamp(),
};
match database_editor
.create_row(&view_id, group_id, params)
.await?
{
None => Err(FlowyError::internal().with_context("Create row fail")),
Some(row) => data_result_ok(RowMetaPB::from(row)), Some(row) => data_result_ok(RowMetaPB::from(row)),
None => Err(FlowyError::internal().with_context("Error creating row")),
} }
} }

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use collab_database::database::MutexDatabase; use collab_database::database::MutexDatabase;
use collab_database::fields::{Field, TypeOptionData}; use collab_database::fields::{Field, TypeOptionData};
use collab_database::rows::{Cell, Cells, CreateRowParams, Row, RowCell, RowDetail, RowId}; use collab_database::rows::{Cell, Cells, Row, RowCell, RowDetail, RowId};
use collab_database::views::{ use collab_database::views::{
DatabaseLayout, DatabaseView, FilterMap, LayoutSetting, OrderObjectPosition, DatabaseLayout, DatabaseView, FilterMap, LayoutSetting, OrderObjectPosition,
}; };
@ -457,20 +457,33 @@ impl DatabaseEditor {
Ok(()) Ok(())
} }
// consider returning a result. But most of the time, it should be fine to just ignore the error. pub async fn duplicate_row(&self, view_id: &str, row_id: &RowId) -> FlowyResult<()> {
pub async fn duplicate_row(&self, view_id: &str, row_id: &RowId) { let (row_detail, index) = {
let params = self.database.lock().duplicate_row(row_id); let database = self.database.lock();
match params {
None => warn!("Failed to duplicate row: {}", row_id), let params = database
Some(params) => { .duplicate_row(row_id)
let result = self.create_row(view_id, None, params).await; .ok_or_else(|| FlowyError::internal().with_context("error while copying row"))?;
if let Some(row_detail) = result.unwrap_or(None) {
let (index, row_order) = database
.create_row_in_view(view_id, params)
.ok_or_else(|| {
FlowyError::internal().with_context("error while inserting duplicated row")
})?;
tracing::trace!("duplicated row: {:?} at {}", row_order, index);
let row_detail = database.get_row_detail(&row_order.id);
(row_detail, index)
};
if let Some(row_detail) = row_detail {
for view in self.database_views.editors().await { for view in self.database_views.editors().await {
view.v_did_duplicate_row(&row_detail).await; view.v_did_create_row(&row_detail, index).await;
} }
} }
},
} Ok(())
} }
pub async fn move_row( pub async fn move_row(
@ -506,18 +519,21 @@ impl DatabaseEditor {
Ok(()) Ok(())
} }
pub async fn create_row( pub async fn create_row(&self, params: CreateRowPayloadPB) -> FlowyResult<Option<RowDetail>> {
&self, let view_editor = self.database_views.get_view_editor(&params.view_id).await?;
view_id: &str,
group_id: Option<String>, let CreateRowParams {
mut params: CreateRowParams, collab_params,
) -> FlowyResult<Option<RowDetail>> { open_after_create: _,
for view in self.database_views.editors().await { } = view_editor.v_will_create_row(params).await?;
view.v_will_create_row(&mut params.cells, &group_id).await;
} let result = self
let result = self.database.lock().create_row_in_view(view_id, params); .database
.lock()
.create_row_in_view(&view_editor.view_id, collab_params);
if let Some((index, row_order)) = result { if let Some((index, row_order)) = result {
tracing::trace!("create row: {:?} at {}", row_order, index); tracing::trace!("created row: {:?} at {}", row_order, index);
let row_detail = self.database.lock().get_row_detail(&row_order.id); let row_detail = self.database.lock().get_row_detail(&row_order.id);
if let Some(row_detail) = row_detail { if let Some(row_detail) = row_detail {
for view in self.database_views.editors().await { for view in self.database_views.editors().await {
@ -1380,9 +1396,9 @@ impl DatabaseViewOperation for DatabaseViewOperationImpl {
to_fut(async move { view }) to_fut(async move { view })
} }
fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<Field>>> { fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Field>> {
let fields = self.database.lock().get_fields_in_view(view_id, field_ids); let fields = self.database.lock().get_fields_in_view(view_id, field_ids);
to_fut(async move { fields.into_iter().map(Arc::new).collect() }) to_fut(async move { fields })
} }
fn get_field(&self, field_id: &str) -> Option<Field> { fn get_field(&self, field_id: &str) -> Option<Field> {

View File

@ -2,10 +2,11 @@ use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use collab_database::database::{gen_database_calculation_id, gen_database_sort_id}; use collab_database::database::{gen_database_calculation_id, gen_database_sort_id, gen_row_id};
use collab_database::fields::{Field, TypeOptionData}; use collab_database::fields::{Field, TypeOptionData};
use collab_database::rows::{Cells, Row, RowDetail, RowId}; use collab_database::rows::{Cells, Row, RowDetail, RowId};
use collab_database::views::{DatabaseLayout, DatabaseView}; use collab_database::views::{DatabaseLayout, DatabaseView};
use lib_infra::util::timestamp;
use tokio::sync::{broadcast, RwLock}; use tokio::sync::{broadcast, RwLock};
use tracing::instrument; use tracing::instrument;
@ -13,14 +14,15 @@ use flowy_error::{FlowyError, FlowyResult};
use lib_dispatch::prelude::af_spawn; use lib_dispatch::prelude::af_spawn;
use crate::entities::{ use crate::entities::{
CalendarEventPB, DatabaseLayoutMetaPB, DatabaseLayoutSettingPB, DeleteSortPayloadPB, FieldType, CalendarEventPB, CreateRowParams, CreateRowPayloadPB, DatabaseLayoutMetaPB,
FieldVisibility, GroupChangesPB, GroupPB, InsertedRowPB, LayoutSettingChangeset, DatabaseLayoutSettingPB, DeleteSortPayloadPB, FieldType, FieldVisibility, GroupChangesPB,
LayoutSettingParams, RemoveCalculationChangesetPB, ReorderSortPayloadPB, RowMetaPB, RowsChangePB, GroupPB, InsertedRowPB, LayoutSettingChangeset, LayoutSettingParams,
RemoveCalculationChangesetPB, ReorderSortPayloadPB, RowMetaPB, RowsChangePB,
SortChangesetNotificationPB, SortPB, UpdateCalculationChangesetPB, UpdateSortPayloadPB, SortChangesetNotificationPB, SortPB, UpdateCalculationChangesetPB, UpdateSortPayloadPB,
}; };
use crate::notification::{send_notification, DatabaseNotification}; use crate::notification::{send_notification, DatabaseNotification};
use crate::services::calculations::{Calculation, CalculationChangeset, CalculationsController}; use crate::services::calculations::{Calculation, CalculationChangeset, CalculationsController};
use crate::services::cell::CellCache; use crate::services::cell::{CellBuilder, CellCache};
use crate::services::database::{database_view_setting_pb_from_view, DatabaseRowEvent, UpdatedRow}; use crate::services::database::{database_view_setting_pb_from_view, DatabaseRowEvent, UpdatedRow};
use crate::services::database_view::view_filter::make_filter_controller; use crate::services::database_view::view_filter::make_filter_controller;
use crate::services::database_view::view_group::{ use crate::services::database_view::view_group::{
@ -115,19 +117,44 @@ impl DatabaseViewEditor {
self.delegate.get_view(&self.view_id).await self.delegate.get_view(&self.view_id).await
} }
pub async fn v_will_create_row(&self, cells: &mut Cells, group_id: &Option<String>) { pub async fn v_will_create_row(
if group_id.is_none() { &self,
return; params: CreateRowPayloadPB,
} ) -> FlowyResult<CreateRowParams> {
let group_id = group_id.as_ref().unwrap(); let mut result = CreateRowParams {
collab_params: collab_database::rows::CreateRowParams {
id: gen_row_id(),
cells: Cells::new(),
height: 60,
visibility: true,
row_position: params.row_position.try_into()?,
timestamp: timestamp(),
},
open_after_create: false,
};
// fill in cells from the frontend
let fields = self.delegate.get_fields(&params.view_id, None).await;
let mut cells = CellBuilder::with_cells(params.data, &fields).build();
// fill in cells according to group_id if supplied
if let Some(group_id) = params.group_id {
let _ = self let _ = self
.mut_group_controller(|group_controller, field| { .mut_group_controller(|group_controller, field| {
group_controller.will_create_row(cells, &field, group_id); group_controller.will_create_row(&mut cells, &field, &group_id);
Ok(()) Ok(())
}) })
.await; .await;
} }
// fill in cells according to active filters
// TODO(RS)
result.collab_params.cells = cells;
Ok(result)
}
pub async fn v_did_update_row_meta(&self, row_id: &RowId, row_detail: &RowDetail) { pub async fn v_did_update_row_meta(&self, row_id: &RowId, row_detail: &RowDetail) {
let update_row = UpdatedRow::new(row_id.as_str()).with_row_meta(row_detail.clone()); let update_row = UpdatedRow::new(row_id.as_str()).with_row_meta(row_detail.clone());
let changeset = RowsChangePB::from_update(update_row.into()); let changeset = RowsChangePB::from_update(update_row.into());
@ -160,13 +187,6 @@ impl DatabaseViewEditor {
.await; .await;
} }
pub async fn v_did_duplicate_row(&self, row_detail: &RowDetail) {
self
.calculations_controller
.did_receive_row_changed(row_detail.row.clone())
.await;
}
#[tracing::instrument(level = "trace", skip_all)] #[tracing::instrument(level = "trace", skip_all)]
pub async fn v_did_delete_row(&self, row: &Row) { pub async fn v_did_delete_row(&self, row: &Row) {
let deleted_row = row.clone(); let deleted_row = row.clone();
@ -796,12 +816,8 @@ impl DatabaseViewEditor {
#[tracing::instrument(level = "debug", skip_all, err)] #[tracing::instrument(level = "debug", skip_all, err)]
pub async fn v_grouping_by_field(&self, field_id: &str) -> FlowyResult<()> { pub async fn v_grouping_by_field(&self, field_id: &str) -> FlowyResult<()> {
if let Some(field) = self.delegate.get_field(field_id) { if let Some(field) = self.delegate.get_field(field_id) {
let new_group_controller = new_group_controller_with_field( let new_group_controller =
self.view_id.clone(), new_group_controller_with_field(self.view_id.clone(), self.delegate.clone(), field).await?;
self.delegate.clone(),
Arc::new(field),
)
.await?;
let new_groups = new_group_controller let new_groups = new_group_controller
.get_all_groups() .get_all_groups()

View File

@ -50,7 +50,7 @@ impl FilterDelegate for DatabaseViewFilterDelegateImpl {
self.0.get_field(field_id) self.0.get_field(field_id)
} }
fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<Field>>> { fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Field>> {
self.0.get_fields(view_id, field_ids) self.0.get_fields(view_id, field_ids)
} }

View File

@ -18,7 +18,7 @@ use crate::services::group::{
pub async fn new_group_controller_with_field( pub async fn new_group_controller_with_field(
view_id: String, view_id: String,
delegate: Arc<dyn DatabaseViewOperation>, delegate: Arc<dyn DatabaseViewOperation>,
grouping_field: Arc<Field>, grouping_field: Field,
) -> FlowyResult<Box<dyn GroupController>> { ) -> FlowyResult<Box<dyn GroupController>> {
let setting_reader = GroupSettingReaderImpl(delegate.clone()); let setting_reader = GroupSettingReaderImpl(delegate.clone());
let rows = delegate.get_rows(&view_id).await; let rows = delegate.get_rows(&view_id).await;

View File

@ -27,7 +27,7 @@ pub trait DatabaseViewOperation: Send + Sync + 'static {
/// Get the view of the database with the view_id /// Get the view of the database with the view_id
fn get_view(&self, view_id: &str) -> Fut<Option<DatabaseView>>; fn get_view(&self, view_id: &str) -> Fut<Option<DatabaseView>>;
/// If the field_ids is None, then it will return all the field revisions /// If the field_ids is None, then it will return all the field revisions
fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<Field>>>; fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Field>>;
/// Returns the field with the field_id /// Returns the field with the field_id
fn get_field(&self, field_id: &str) -> Option<Field>; fn get_field(&self, field_id: &str) -> Option<Field>;

View File

@ -74,7 +74,7 @@ impl SortDelegate for DatabaseViewSortDelegateImpl {
self.delegate.get_field(field_id) self.delegate.get_field(field_id)
} }
fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<Field>>> { fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Field>> {
self.delegate.get_fields(view_id, field_ids) self.delegate.get_fields(view_id, field_ids)
} }
} }

View File

@ -22,7 +22,7 @@ use crate::services::filter::{Filter, FilterChangeset, FilterInner, FilterResult
pub trait FilterDelegate: Send + Sync + 'static { pub trait FilterDelegate: Send + Sync + 'static {
fn get_field(&self, field_id: &str) -> Option<Field>; fn get_field(&self, field_id: &str) -> Option<Field>;
fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<Field>>>; fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Field>>;
fn get_rows(&self, view_id: &str) -> Fut<Vec<Arc<RowDetail>>>; fn get_rows(&self, view_id: &str) -> Fut<Vec<Arc<RowDetail>>>;
fn get_row(&self, view_id: &str, rows_id: &RowId) -> Fut<Option<(usize, Arc<RowDetail>)>>; fn get_row(&self, view_id: &str, rows_id: &RowId) -> Fut<Option<(usize, Arc<RowDetail>)>>;
fn save_filters(&self, view_id: &str, filters: &[Filter]); fn save_filters(&self, view_id: &str, filters: &[Filter]);
@ -116,14 +116,14 @@ impl FilterController {
}); });
} }
async fn get_field_map(&self) -> HashMap<String, Arc<Field>> { async fn get_field_map(&self) -> HashMap<String, Field> {
self self
.delegate .delegate
.get_fields(&self.view_id, None) .get_fields(&self.view_id, None)
.await .await
.into_iter() .into_iter()
.map(|field| (field.id.clone(), field)) .map(|field| (field.id.clone(), field))
.collect::<HashMap<String, Arc<Field>>>() .collect::<HashMap<String, Field>>()
} }
#[tracing::instrument( #[tracing::instrument(
@ -333,7 +333,7 @@ impl FilterController {
fn filter_row( fn filter_row(
row: &Row, row: &Row,
result_by_row_id: &DashMap<RowId, bool>, result_by_row_id: &DashMap<RowId, bool>,
field_by_field_id: &HashMap<String, Arc<Field>>, field_by_field_id: &HashMap<String, Field>,
cell_data_cache: &CellCache, cell_data_cache: &CellCache,
filters: &Vec<Filter>, filters: &Vec<Filter>,
) -> Option<(RowId, bool)> { ) -> Option<(RowId, bool)> {
@ -360,7 +360,7 @@ fn filter_row(
/// Recursively applies a `Filter` to a `Row`'s cells. /// Recursively applies a `Filter` to a `Row`'s cells.
fn apply_filter( fn apply_filter(
row: &Row, row: &Row,
field_by_field_id: &HashMap<String, Arc<Field>>, field_by_field_id: &HashMap<String, Field>,
cell_data_cache: &CellCache, cell_data_cache: &CellCache,
filter: &Filter, filter: &Filter,
) -> Option<bool> { ) -> Option<bool> {
@ -405,14 +405,10 @@ fn apply_filter(
} }
let cell = row.cells.get(field_id).cloned(); let cell = row.cells.get(field_id).cloned();
let field_type = FieldType::from(field.field_type); let field_type = FieldType::from(field.field_type);
if let Some(handler) = TypeOptionCellExt::new(field.as_ref(), Some(cell_data_cache.clone())) if let Some(handler) = TypeOptionCellExt::new(field, Some(cell_data_cache.clone()))
.get_type_option_cell_data_handler(&field_type) .get_type_option_cell_data_handler(&field_type)
{ {
Some(handler.handle_cell_filter( Some(handler.handle_cell_filter(field, &cell.unwrap_or_default(), condition_and_content))
field.as_ref(),
&cell.unwrap_or_default(),
condition_and_content,
))
} else { } else {
Some(true) Some(true)
} }

View File

@ -71,7 +71,7 @@ pub struct GroupContext<C> {
configuration_phantom: PhantomData<C>, configuration_phantom: PhantomData<C>,
/// The grouping field /// The grouping field
field: Arc<Field>, field: Field,
/// Cache all the groups. Cache the group by its id. /// Cache all the groups. Cache the group by its id.
/// We use the id of the [Field] as the [No Status] group id. /// We use the id of the [Field] as the [No Status] group id.
@ -94,7 +94,7 @@ where
#[tracing::instrument(level = "trace", skip_all, err)] #[tracing::instrument(level = "trace", skip_all, err)]
pub async fn new( pub async fn new(
view_id: String, view_id: String,
field: Arc<Field>, field: Field,
reader: Arc<dyn GroupSettingReader>, reader: Arc<dyn GroupSettingReader>,
writer: Arc<dyn GroupSettingWriter>, writer: Arc<dyn GroupSettingWriter>,
) -> FlowyResult<Self> { ) -> FlowyResult<Self> {

View File

@ -1,5 +1,4 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use collab_database::fields::{Field, TypeOptionData}; use collab_database::fields::{Field, TypeOptionData};
@ -75,7 +74,7 @@ where
I: GroupOperationInterceptor<GroupTypeOption = T> + Send + Sync, I: GroupOperationInterceptor<GroupTypeOption = T> + Send + Sync,
{ {
pub async fn new( pub async fn new(
grouping_field: &Arc<Field>, grouping_field: &Field,
mut configuration: GroupContext<C>, mut configuration: GroupContext<C>,
operation_interceptor: I, operation_interceptor: I,
) -> FlowyResult<Self> { ) -> FlowyResult<Self> {

View File

@ -1,5 +1,3 @@
use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use collab_database::fields::{Field, TypeOptionData}; use collab_database::fields::{Field, TypeOptionData};
use collab_database::rows::{Cells, Row, RowDetail, RowId}; use collab_database::rows::{Cells, Row, RowDetail, RowId};
@ -26,7 +24,7 @@ pub struct DefaultGroupController {
const DEFAULT_GROUP_CONTROLLER: &str = "DefaultGroupController"; const DEFAULT_GROUP_CONTROLLER: &str = "DefaultGroupController";
impl DefaultGroupController { impl DefaultGroupController {
pub fn new(field: &Arc<Field>) -> Self { pub fn new(field: &Field) -> Self {
let group = GroupData::new( let group = GroupData::new(
DEFAULT_GROUP_CONTROLLER.to_owned(), DEFAULT_GROUP_CONTROLLER.to_owned(),
field.id.clone(), field.id.clone(),

View File

@ -96,7 +96,7 @@ impl RowChangeset {
)] )]
pub async fn make_group_controller<R, W, TW>( pub async fn make_group_controller<R, W, TW>(
view_id: String, view_id: String,
grouping_field: Arc<Field>, grouping_field: Field,
row_details: Vec<Arc<RowDetail>>, row_details: Vec<Arc<RowDetail>>,
setting_reader: R, setting_reader: R,
setting_writer: W, setting_writer: W,
@ -200,10 +200,7 @@ where
} }
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn find_new_grouping_field( pub fn find_new_grouping_field(fields: &[Field], _layout: &DatabaseLayout) -> Option<Field> {
fields: &[Arc<Field>],
_layout: &DatabaseLayout,
) -> Option<Arc<Field>> {
let mut groupable_field_revs = fields let mut groupable_field_revs = fields
.iter() .iter()
.flat_map(|field_rev| { .flat_map(|field_rev| {
@ -213,7 +210,7 @@ pub fn find_new_grouping_field(
false => None, false => None,
} }
}) })
.collect::<Vec<Arc<Field>>>(); .collect::<Vec<Field>>();
if groupable_field_revs.is_empty() { if groupable_field_revs.is_empty() {
// If there is not groupable fields then we use the primary field. // If there is not groupable fields then we use the primary field.

View File

@ -30,7 +30,7 @@ pub trait SortDelegate: Send + Sync {
/// Returns all the rows after applying grid's filter /// Returns all the rows after applying grid's filter
fn get_rows(&self, view_id: &str) -> Fut<Vec<Arc<RowDetail>>>; fn get_rows(&self, view_id: &str) -> Fut<Vec<Arc<RowDetail>>>;
fn get_field(&self, field_id: &str) -> Option<Field>; fn get_field(&self, field_id: &str) -> Option<Field>;
fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<Field>>>; fn get_fields(&self, view_id: &str, field_ids: Option<Vec<String>>) -> Fut<Vec<Field>>;
} }
pub struct SortController { pub struct SortController {
@ -290,7 +290,7 @@ fn cmp_row(
left: &Row, left: &Row,
right: &Row, right: &Row,
sort: &Arc<Sort>, sort: &Arc<Sort>,
fields: &[Arc<Field>], fields: &[Field],
cell_data_cache: &CellCache, cell_data_cache: &CellCache,
) -> Ordering { ) -> Ordering {
match fields match fields
@ -335,18 +335,16 @@ fn cmp_row(
fn cmp_cell( fn cmp_cell(
left_cell: Option<&Cell>, left_cell: Option<&Cell>,
right_cell: Option<&Cell>, right_cell: Option<&Cell>,
field: &Arc<Field>, field: &Field,
field_type: FieldType, field_type: FieldType,
cell_data_cache: &CellCache, cell_data_cache: &CellCache,
sort_condition: SortCondition, sort_condition: SortCondition,
) -> Ordering { ) -> Ordering {
match TypeOptionCellExt::new(field.as_ref(), Some(cell_data_cache.clone())) match TypeOptionCellExt::new(field, Some(cell_data_cache.clone()))
.get_type_option_cell_data_handler(&field_type) .get_type_option_cell_data_handler(&field_type)
{ {
None => default_order(), None => default_order(),
Some(handler) => { Some(handler) => handler.handle_cell_compare(left_cell, right_cell, field, sort_condition),
handler.handle_cell_compare(left_cell, right_cell, field.as_ref(), sort_condition)
},
} }
} }

View File

@ -1,7 +1,6 @@
use collab_database::database::gen_row_id;
use collab_database::rows::RowId; use collab_database::rows::RowId;
use lib_infra::util::timestamp; use flowy_database2::entities::CreateRowPayloadPB;
use crate::database::database_editor::DatabaseEditorTest; use crate::database::database_editor::DatabaseEditorTest;
@ -30,17 +29,11 @@ impl DatabaseRowTest {
pub async fn run_script(&mut self, script: RowScript) { pub async fn run_script(&mut self, script: RowScript) {
match script { match script {
RowScript::CreateEmptyRow => { RowScript::CreateEmptyRow => {
let params = collab_database::rows::CreateRowParams { let params = CreateRowPayloadPB {
id: gen_row_id(), view_id: self.view_id.clone(),
timestamp: timestamp(),
..Default::default() ..Default::default()
}; };
let row_detail = self let row_detail = self.editor.create_row(params).await.unwrap().unwrap();
.editor
.create_row(&self.view_id, None, params)
.await
.unwrap()
.unwrap();
self self
.row_by_row_id .row_by_row_id
.insert(row_detail.row.id.to_string(), row_detail.into()); .insert(row_detail.row.id.to_string(), row_detail.into());

View File

@ -3,12 +3,8 @@ use std::vec;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use chrono::{offset, Duration}; use chrono::{offset, Duration};
use collab_database::database::gen_row_id;
use collab_database::rows::CreateRowParams;
use collab_database::views::OrderObjectPosition; use flowy_database2::entities::{CreateRowPayloadPB, FieldType};
use flowy_database2::entities::FieldType;
use flowy_database2::services::cell::CellBuilder;
use flowy_database2::services::field::DateCellData; use flowy_database2::services::field::DateCellData;
use crate::database::group_test::script::DatabaseGroupTest; use crate::database::group_test::script::DatabaseGroupTest;
@ -26,19 +22,17 @@ async fn group_by_date_test() {
.unwrap() .unwrap()
.timestamp() .timestamp()
.to_string(); .to_string();
let mut cells = HashMap::new(); let mut cells = HashMap::new();
cells.insert(date_field.id.clone(), timestamp); cells.insert(date_field.id.clone(), timestamp);
let cells = CellBuilder::with_cells(cells, &[date_field.clone()]).build();
let params = CreateRowParams { let params = CreateRowPayloadPB {
id: gen_row_id(), view_id: test.view_id.clone(),
cells, data: cells,
height: 60, ..Default::default()
visibility: true,
row_position: OrderObjectPosition::default(),
timestamp: 0,
}; };
let res = test.editor.create_row(&test.view_id, None, params).await;
let res = test.editor.create_row(params).await;
assert!(res.is_ok()); assert!(res.is_ok());
} }

View File

@ -1,8 +1,7 @@
use collab_database::database::gen_row_id;
use collab_database::fields::Field; use collab_database::fields::Field;
use collab_database::rows::{CreateRowParams, RowId}; use collab_database::rows::RowId;
use flowy_database2::entities::{FieldType, GroupPB, RowMetaPB}; use flowy_database2::entities::{CreateRowPayloadPB, FieldType, GroupPB, RowMetaPB};
use flowy_database2::services::cell::{ use flowy_database2::services::cell::{
delete_select_option_cell, insert_date_cell, insert_select_option_cell, insert_url_cell, delete_select_option_cell, insert_date_cell, insert_select_option_cell, insert_url_cell,
}; };
@ -10,7 +9,6 @@ use flowy_database2::services::field::{
edit_single_select_type_option, SelectOption, SelectTypeOptionSharedAction, edit_single_select_type_option, SelectOption, SelectTypeOptionSharedAction,
SingleSelectTypeOption, SingleSelectTypeOption,
}; };
use lib_infra::util::timestamp;
use crate::database::database_editor::DatabaseEditorTest; use crate::database::database_editor::DatabaseEditorTest;
@ -138,16 +136,13 @@ impl DatabaseGroupTest {
}, },
GroupScript::CreateRow { group_index } => { GroupScript::CreateRow { group_index } => {
let group = self.group_at_index(group_index).await; let group = self.group_at_index(group_index).await;
let params = CreateRowParams { let params = CreateRowPayloadPB {
id: gen_row_id(), view_id: self.view_id.clone(),
timestamp: timestamp(), row_position: Default::default(),
..Default::default() group_id: Some(group.group_id),
data: Default::default(),
}; };
let _ = self let _ = self.editor.create_row(params).await.unwrap();
.editor
.create_row(&self.view_id, Some(group.group_id.clone()), params)
.await
.unwrap();
}, },
GroupScript::DeleteRow { GroupScript::DeleteRow {
group_index, group_index,

View File

@ -8,7 +8,7 @@ use futures::stream::StreamExt;
use tokio::sync::broadcast::Receiver; use tokio::sync::broadcast::Receiver;
use flowy_database2::entities::{ use flowy_database2::entities::{
DeleteSortPayloadPB, FieldType, ReorderSortPayloadPB, UpdateSortPayloadPB, CreateRowPayloadPB, DeleteSortPayloadPB, FieldType, ReorderSortPayloadPB, UpdateSortPayloadPB,
}; };
use flowy_database2::services::cell::stringify_cell_data; use flowy_database2::services::cell::stringify_cell_data;
use flowy_database2::services::database_view::DatabaseViewChanged; use flowy_database2::services::database_view::DatabaseViewChanged;
@ -155,15 +155,10 @@ impl DatabaseSortTest {
); );
self self
.editor .editor
.create_row( .create_row(CreateRowPayloadPB {
&self.view_id, view_id: self.view_id.clone(),
None,
collab_database::rows::CreateRowParams {
id: collab_database::database::gen_row_id(),
timestamp: collab_database::database::timestamp(),
..Default::default() ..Default::default()
}, })
)
.await .await
.unwrap(); .unwrap();
}, },