refactor: read cell data

This commit is contained in:
appflowy 2022-06-24 18:13:40 +08:00
parent 0f868f48f3
commit b73c68c6f6
21 changed files with 108 additions and 132 deletions

View File

@ -70,7 +70,7 @@ class _GridBlockListener {
void _handler(GridNotification ty, Either<Uint8List, FlowyError> result) { void _handler(GridNotification ty, Either<Uint8List, FlowyError> result) {
switch (ty) { switch (ty) {
case GridNotification.DidUpdateGridRow: case GridNotification.DidUpdateGridBlock:
result.fold( result.fold(
(payload) => _rowsUpdateNotifier?.value = left([GridRowsChangeset.fromBuffer(payload)]), (payload) => _rowsUpdateNotifier?.value = left([GridRowsChangeset.fromBuffer(payload)]),
(error) => _rowsUpdateNotifier?.value = right(error), (error) => _rowsUpdateNotifier?.value = right(error),

View File

@ -6,7 +6,7 @@ const OBSERVABLE_CATEGORY: &str = "Grid";
pub enum GridNotification { pub enum GridNotification {
Unknown = 0, Unknown = 0,
DidCreateBlock = 11, DidCreateBlock = 11,
DidUpdateGridRow = 20, DidUpdateGridBlock = 20,
DidUpdateGridField = 21, DidUpdateGridField = 21,
DidUpdateRow = 30, DidUpdateRow = 30,
DidUpdateCell = 40, DidUpdateCell = 40,

View File

@ -9,7 +9,7 @@ use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
use std::sync::Arc; use std::sync::Arc;
#[tracing::instrument(level = "trace", skip(data, manager), err)] #[tracing::instrument(level = "trace", skip(data, manager), err)]
pub(crate) async fn get_grid_data_handler( pub(crate) async fn get_grid_handler(
data: Data<GridId>, data: Data<GridId>,
manager: AppData<Arc<GridManager>>, manager: AppData<Arc<GridManager>>,
) -> DataResult<Grid, FlowyError> { ) -> DataResult<Grid, FlowyError> {

View File

@ -8,7 +8,7 @@ use strum_macros::Display;
pub fn create(grid_manager: Arc<GridManager>) -> Module { pub fn create(grid_manager: Arc<GridManager>) -> Module {
let mut module = Module::new().name(env!("CARGO_PKG_NAME")).data(grid_manager); let mut module = Module::new().name(env!("CARGO_PKG_NAME")).data(grid_manager);
module = module module = module
.event(GridEvent::GetGridData, get_grid_data_handler) .event(GridEvent::GetGrid, get_grid_handler)
.event(GridEvent::GetGridBlocks, get_grid_blocks_handler) .event(GridEvent::GetGridBlocks, get_grid_blocks_handler)
.event(GridEvent::GetGridSetting, get_grid_setting_handler) .event(GridEvent::GetGridSetting, get_grid_setting_handler)
.event(GridEvent::UpdateGridSetting, update_grid_setting_handler) .event(GridEvent::UpdateGridSetting, update_grid_setting_handler)
@ -46,7 +46,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
#[event_err = "FlowyError"] #[event_err = "FlowyError"]
pub enum GridEvent { pub enum GridEvent {
#[event(input = "GridId", output = "Grid")] #[event(input = "GridId", output = "Grid")]
GetGridData = 0, GetGrid = 0,
#[event(input = "QueryGridBlocksPayload", output = "RepeatedGridBlock")] #[event(input = "QueryGridBlocksPayload", output = "RepeatedGridBlock")]
GetGridBlocks = 1, GetGridBlocks = 1,

View File

@ -156,23 +156,8 @@ pub async fn make_grid_view_data(
grid_manager: Arc<GridManager>, grid_manager: Arc<GridManager>,
build_context: BuildGridContext, build_context: BuildGridContext,
) -> FlowyResult<Bytes> { ) -> FlowyResult<Bytes> {
let grid_rev = GridRevision { for block_meta_data in &build_context.blocks_meta_data {
grid_id: view_id.to_string(), let block_id = &block_meta_data.block_id;
fields: build_context.field_revs,
blocks: build_context.blocks,
setting: GridSettingRevision::default(),
};
// Create grid
let grid_meta_delta = make_grid_delta(&grid_rev);
let grid_delta_data = grid_meta_delta.to_delta_bytes();
let repeated_revision: RepeatedRevision =
Revision::initial_revision(user_id, view_id, grid_delta_data.clone()).into();
let _ = grid_manager.create_grid(view_id, repeated_revision).await?;
for block_meta_data in build_context.blocks_meta_data {
let block_id = block_meta_data.block_id.clone();
// Indexing the block's rows // Indexing the block's rows
block_meta_data.rows.iter().for_each(|row| { block_meta_data.rows.iter().for_each(|row| {
let _ = grid_manager.block_index_cache.insert(&row.block_id, &row.id); let _ = grid_manager.block_index_cache.insert(&row.block_id, &row.id);
@ -188,5 +173,14 @@ pub async fn make_grid_view_data(
.await?; .await?;
} }
let grid_rev = GridRevision::from_build_context(view_id, build_context);
// Create grid
let grid_meta_delta = make_grid_delta(&grid_rev);
let grid_delta_data = grid_meta_delta.to_delta_bytes();
let repeated_revision: RepeatedRevision =
Revision::initial_revision(user_id, view_id, grid_delta_data.clone()).into();
let _ = grid_manager.create_grid(view_id, repeated_revision).await?;
Ok(grid_delta_data) Ok(grid_delta_data)
} }

View File

@ -19,6 +19,7 @@ use std::sync::Arc;
type BlockId = String; type BlockId = String;
pub(crate) struct GridBlockManager { pub(crate) struct GridBlockManager {
#[allow(dead_code)]
grid_id: String, grid_id: String,
user: Arc<dyn GridUser>, user: Arc<dyn GridUser>,
persistence: Arc<BlockIndexCache>, persistence: Arc<BlockIndexCache>,
@ -29,10 +30,10 @@ impl GridBlockManager {
pub(crate) async fn new( pub(crate) async fn new(
grid_id: &str, grid_id: &str,
user: &Arc<dyn GridUser>, user: &Arc<dyn GridUser>,
blocks: Vec<GridBlockRevision>, block_revs: Vec<Arc<GridBlockRevision>>,
persistence: Arc<BlockIndexCache>, persistence: Arc<BlockIndexCache>,
) -> FlowyResult<Self> { ) -> FlowyResult<Self> {
let editor_map = make_block_meta_editor_map(user, blocks).await?; let editor_map = make_block_meta_editor_map(user, block_revs).await?;
let user = user.clone(); let user = user.clone();
let grid_id = grid_id.to_owned(); let grid_id = grid_id.to_owned();
let manager = Self { let manager = Self {
@ -246,7 +247,7 @@ impl GridBlockManager {
} }
async fn notify_did_update_block(&self, block_id: &str, changeset: GridRowsChangeset) -> FlowyResult<()> { async fn notify_did_update_block(&self, block_id: &str, changeset: GridRowsChangeset) -> FlowyResult<()> {
send_dart_notification(block_id, GridNotification::DidUpdateGridRow) send_dart_notification(block_id, GridNotification::DidUpdateGridBlock)
.payload(changeset) .payload(changeset)
.send(); .send();
Ok(()) Ok(())
@ -261,12 +262,12 @@ impl GridBlockManager {
async fn make_block_meta_editor_map( async fn make_block_meta_editor_map(
user: &Arc<dyn GridUser>, user: &Arc<dyn GridUser>,
blocks: Vec<GridBlockRevision>, block_revs: Vec<Arc<GridBlockRevision>>,
) -> FlowyResult<DashMap<String, Arc<GridBlockRevisionEditor>>> { ) -> FlowyResult<DashMap<String, Arc<GridBlockRevisionEditor>>> {
let editor_map = DashMap::new(); let editor_map = DashMap::new();
for block in blocks { for block_rev in block_revs {
let editor = make_block_meta_editor(user, &block.block_id).await?; let editor = make_block_meta_editor(user, &block_rev.block_id).await?;
editor_map.insert(block.block_id, Arc::new(editor)); editor_map.insert(block_rev.block_id.clone(), Arc::new(editor));
} }
Ok(editor_map) Ok(editor_map)

View File

@ -42,28 +42,28 @@ impl GridBlockRevisionEditor {
}) })
} }
pub async fn duplicate_block_meta_data(&self, duplicated_block_id: &str) -> GridBlockRevisionData { pub async fn duplicate_block(&self, duplicated_block_id: &str) -> GridBlockRevisionData {
self.pad.read().await.duplicate_data(duplicated_block_id).await self.pad.read().await.duplicate_data(duplicated_block_id).await
} }
/// return current number of rows and the inserted index. The inserted index will be None if the start_row_id is None /// Create a row after the the with prev_row_id. If prev_row_id is None, the row will be appended to the list
pub(crate) async fn create_row( pub(crate) async fn create_row(
&self, &self,
row: RowRevision, row: RowRevision,
start_row_id: Option<String>, prev_row_id: Option<String>,
) -> FlowyResult<(i32, Option<i32>)> { ) -> FlowyResult<(i32, Option<i32>)> {
let mut row_count = 0; let mut row_count = 0;
let mut row_index = None; let mut row_index = None;
let _ = self let _ = self
.modify(|block_pad| { .modify(|block_pad| {
if let Some(start_row_id) = start_row_id.as_ref() { if let Some(start_row_id) = prev_row_id.as_ref() {
match block_pad.index_of_row(start_row_id) { match block_pad.index_of_row(start_row_id) {
None => {} None => {}
Some(index) => row_index = Some(index + 1), Some(index) => row_index = Some(index + 1),
} }
} }
let change = block_pad.add_row_rev(row, start_row_id)?; let change = block_pad.add_row_rev(row, prev_row_id)?;
row_count = block_pad.number_of_rows(); row_count = block_pad.number_of_rows();
if row_index.is_none() { if row_index.is_none() {

View File

@ -93,7 +93,7 @@ mod tests {
use crate::services::field::type_options::checkbox_type_option::{NO, YES}; use crate::services::field::type_options::checkbox_type_option::{NO, YES};
use crate::services::field::FieldBuilder; use crate::services::field::FieldBuilder;
use crate::services::row::{apply_cell_data_changeset, decode_cell_data_from_type_option_cell_data}; use crate::services::row::{apply_cell_data_changeset, decode_cell_data};
use flowy_grid_data_model::entities::FieldType; use flowy_grid_data_model::entities::FieldType;
@ -101,39 +101,21 @@ mod tests {
fn checkout_box_description_test() { fn checkout_box_description_test() {
let field_rev = FieldBuilder::from_field_type(&FieldType::Checkbox).build(); let field_rev = FieldBuilder::from_field_type(&FieldType::Checkbox).build();
let data = apply_cell_data_changeset("true", None, &field_rev).unwrap(); let data = apply_cell_data_changeset("true", None, &field_rev).unwrap();
assert_eq!( assert_eq!(decode_cell_data(data, &field_rev).to_string(), YES);
decode_cell_data_from_type_option_cell_data(data, &field_rev, &field_rev.field_type).to_string(),
YES
);
let data = apply_cell_data_changeset("1", None, &field_rev).unwrap(); let data = apply_cell_data_changeset("1", None, &field_rev).unwrap();
assert_eq!( assert_eq!(decode_cell_data(data, &field_rev,).to_string(), YES);
decode_cell_data_from_type_option_cell_data(data, &field_rev, &field_rev.field_type).to_string(),
YES
);
let data = apply_cell_data_changeset("yes", None, &field_rev).unwrap(); let data = apply_cell_data_changeset("yes", None, &field_rev).unwrap();
assert_eq!( assert_eq!(decode_cell_data(data, &field_rev,).to_string(), YES);
decode_cell_data_from_type_option_cell_data(data, &field_rev, &field_rev.field_type).to_string(),
YES
);
let data = apply_cell_data_changeset("false", None, &field_rev).unwrap(); let data = apply_cell_data_changeset("false", None, &field_rev).unwrap();
assert_eq!( assert_eq!(decode_cell_data(data, &field_rev,).to_string(), NO);
decode_cell_data_from_type_option_cell_data(data, &field_rev, &field_rev.field_type).to_string(),
NO
);
let data = apply_cell_data_changeset("no", None, &field_rev).unwrap(); let data = apply_cell_data_changeset("no", None, &field_rev).unwrap();
assert_eq!( assert_eq!(decode_cell_data(data, &field_rev,).to_string(), NO);
decode_cell_data_from_type_option_cell_data(data, &field_rev, &field_rev.field_type).to_string(),
NO
);
let data = apply_cell_data_changeset("12", None, &field_rev).unwrap(); let data = apply_cell_data_changeset("12", None, &field_rev).unwrap();
assert_eq!( assert_eq!(decode_cell_data(data, &field_rev,).to_string(), NO);
decode_cell_data_from_type_option_cell_data(data, &field_rev, &field_rev.field_type).to_string(),
NO
);
} }
} }

View File

@ -1,6 +1,6 @@
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use crate::services::row::{decode_cell_data, CellContentChangeset, CellDataOperation, DecodedCellData}; use crate::services::row::{try_decode_cell_data, CellContentChangeset, CellDataOperation, DecodedCellData};
use bytes::Bytes; use bytes::Bytes;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
@ -45,7 +45,7 @@ impl CellDataOperation<String> for RichTextTypeOption {
|| decoded_field_type.is_multi_select() || decoded_field_type.is_multi_select()
|| decoded_field_type.is_number() || decoded_field_type.is_number()
{ {
decode_cell_data(encoded_data, decoded_field_type, decoded_field_type, field_rev) try_decode_cell_data(encoded_data, field_rev, decoded_field_type, decoded_field_type)
} else { } else {
let cell_data = encoded_data.into(); let cell_data = encoded_data.into();
Ok(DecodedCellData::new(cell_data)) Ok(DecodedCellData::new(cell_data))

View File

@ -46,9 +46,9 @@ impl GridRevisionEditor {
let grid_pad = rev_manager.load::<GridPadBuilder>(Some(cloud)).await?; let grid_pad = rev_manager.load::<GridPadBuilder>(Some(cloud)).await?;
let rev_manager = Arc::new(rev_manager); let rev_manager = Arc::new(rev_manager);
let grid_pad = Arc::new(RwLock::new(grid_pad)); let grid_pad = Arc::new(RwLock::new(grid_pad));
let blocks = grid_pad.read().await.get_block_revs(); let block_revs = grid_pad.read().await.get_block_revs();
let block_meta_manager = Arc::new(GridBlockManager::new(grid_id, &user, blocks, persistence).await?); let block_meta_manager = Arc::new(GridBlockManager::new(grid_id, &user, block_revs, persistence).await?);
Ok(Arc::new(Self { Ok(Arc::new(Self {
grid_id: grid_id.to_owned(), grid_id: grid_id.to_owned(),
user, user,
@ -342,7 +342,10 @@ impl GridRevisionEditor {
pub async fn get_cell(&self, params: &CellIdentifier) -> Option<Cell> { pub async fn get_cell(&self, params: &CellIdentifier) -> Option<Cell> {
let field_rev = self.get_field_rev(&params.field_id).await?; let field_rev = self.get_field_rev(&params.field_id).await?;
let row_rev = self.block_manager.get_row_rev(&params.row_id).await.ok()??; let row_rev = self.block_manager.get_row_rev(&params.row_id).await.ok()??;
make_cell(&params.field_id, &field_rev, &row_rev)
let cell_rev = row_rev.cells.get(&params.field_id)?.clone();
let data = decode_cell_data(cell_rev.data, &field_rev).data;
Some(Cell::new(&params.field_id, data))
} }
pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> { pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> {
@ -405,7 +408,7 @@ impl GridRevisionEditor {
make_grid_blocks(block_ids, block_snapshots) make_grid_blocks(block_ids, block_snapshots)
} }
pub async fn get_block_metas(&self) -> FlowyResult<Vec<GridBlockRevision>> { pub async fn get_block_metas(&self) -> FlowyResult<Vec<Arc<GridBlockRevision>>> {
let grid_blocks = self.grid_pad.read().await.get_block_revs(); let grid_blocks = self.grid_pad.read().await.get_block_revs();
Ok(grid_blocks) Ok(grid_blocks)
} }
@ -422,10 +425,10 @@ impl GridRevisionEditor {
let pad_read_guard = self.grid_pad.read().await; let pad_read_guard = self.grid_pad.read().await;
let field_orders = pad_read_guard.get_field_orders(); let field_orders = pad_read_guard.get_field_orders();
let mut block_orders = vec![]; let mut block_orders = vec![];
for block_order in pad_read_guard.get_block_revs() { for block_rev in pad_read_guard.get_block_revs() {
let row_orders = self.block_manager.get_row_orders(&block_order.block_id).await?; let row_orders = self.block_manager.get_row_orders(&block_rev.block_id).await?;
let block_order = GridBlock { let block_order = GridBlock {
id: block_order.block_id, id: block_rev.block_id.clone(),
row_orders, row_orders,
}; };
block_orders.push(block_order); block_orders.push(block_order);
@ -467,8 +470,8 @@ impl GridRevisionEditor {
.read() .read()
.await .await
.get_block_revs() .get_block_revs()
.into_iter() .iter()
.map(|block_meta| block_meta.block_id) .map(|block_rev| block_rev.block_id.clone())
.collect::<Vec<String>>(), .collect::<Vec<String>>(),
Some(block_ids) => block_ids, Some(block_ids) => block_ids,
}; };
@ -526,9 +529,7 @@ impl GridRevisionEditor {
let duplicated_block_id = &duplicated_blocks[index].block_id; let duplicated_block_id = &duplicated_blocks[index].block_id;
tracing::trace!("Duplicate block:{} meta data", duplicated_block_id); tracing::trace!("Duplicate block:{} meta data", duplicated_block_id);
let duplicated_block_meta_data = grid_block_meta_editor let duplicated_block_meta_data = grid_block_meta_editor.duplicate_block(duplicated_block_id).await;
.duplicate_block_meta_data(duplicated_block_id)
.await;
blocks_meta_data.push(duplicated_block_meta_data); blocks_meta_data.push(duplicated_block_meta_data);
} }
} else { } else {

View File

@ -55,12 +55,6 @@ pub struct TypeOptionCellData {
pub field_type: FieldType, pub field_type: FieldType,
} }
impl TypeOptionCellData {
pub fn split(self) -> (String, FieldType) {
(self.data, self.field_type)
}
}
impl std::str::FromStr for TypeOptionCellData { impl std::str::FromStr for TypeOptionCellData {
type Err = FlowyError; type Err = FlowyError;
@ -139,14 +133,11 @@ pub fn apply_cell_data_changeset<T: Into<CellContentChangeset>>(
Ok(TypeOptionCellData::new(s, field_rev.field_type.clone()).json()) Ok(TypeOptionCellData::new(s, field_rev.field_type.clone()).json())
} }
pub fn decode_cell_data_from_type_option_cell_data<T: TryInto<TypeOptionCellData>>( pub fn decode_cell_data<T: TryInto<TypeOptionCellData>>(data: T, field_rev: &FieldRevision) -> DecodedCellData {
data: T,
field_rev: &FieldRevision,
field_type: &FieldType,
) -> DecodedCellData {
if let Ok(type_option_cell_data) = data.try_into() { if let Ok(type_option_cell_data) = data.try_into() {
let (encoded_data, s_field_type) = type_option_cell_data.split(); let TypeOptionCellData { data, field_type } = type_option_cell_data;
match decode_cell_data(encoded_data, &s_field_type, field_type, field_rev) { let to_field_type = &field_rev.field_type;
match try_decode_cell_data(data, &field_rev, &field_type, to_field_type) {
Ok(cell_data) => cell_data, Ok(cell_data) => cell_data,
Err(e) => { Err(e) => {
tracing::error!("Decode cell data failed, {:?}", e); tracing::error!("Decode cell data failed, {:?}", e);
@ -159,11 +150,11 @@ pub fn decode_cell_data_from_type_option_cell_data<T: TryInto<TypeOptionCellData
} }
} }
pub fn decode_cell_data<T: Into<String>>( pub fn try_decode_cell_data<T: Into<String>>(
encoded_data: T, encoded_data: T,
field_rev: &FieldRevision,
s_field_type: &FieldType, s_field_type: &FieldType,
t_field_type: &FieldType, t_field_type: &FieldType,
field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<DecodedCellData> {
let encoded_data = encoded_data.into(); let encoded_data = encoded_data.into();
let get_cell_data = || { let get_cell_data = || {

View File

@ -1,4 +1,4 @@
use crate::services::row::decode_cell_data_from_type_option_cell_data; use crate::services::row::decode_cell_data;
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
use flowy_grid_data_model::entities::{Cell, GridBlock, RepeatedGridBlock, Row, RowOrder}; use flowy_grid_data_model::entities::{Cell, GridBlock, RepeatedGridBlock, Row, RowOrder};
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, RowRevision}; use flowy_grid_data_model::revision::{CellRevision, FieldRevision, RowRevision};
@ -24,23 +24,17 @@ pub(crate) fn block_from_row_orders(row_orders: Vec<RowOrder>) -> Vec<GridBlock>
} }
#[inline(always)] #[inline(always)]
pub fn make_cell_by_field_id( fn make_cell_by_field_id(
field_map: &HashMap<&String, &FieldRevision>, field_map: &HashMap<&String, &FieldRevision>,
field_id: String, field_id: String,
cell_rev: CellRevision, cell_rev: CellRevision,
) -> Option<(String, Cell)> { ) -> Option<(String, Cell)> {
let field_rev = field_map.get(&field_id)?; let field_rev = field_map.get(&field_id)?;
let data = decode_cell_data_from_type_option_cell_data(cell_rev.data, field_rev, &field_rev.field_type).data; let data = decode_cell_data(cell_rev.data, field_rev).data;
let cell = Cell::new(&field_id, data); let cell = Cell::new(&field_id, data);
Some((field_id, cell)) Some((field_id, cell))
} }
pub fn make_cell(field_id: &str, field_rev: &FieldRevision, row_rev: &RowRevision) -> Option<Cell> {
let cell_rev = row_rev.cells.get(field_id)?.clone();
let data = decode_cell_data_from_type_option_cell_data(cell_rev.data, field_rev, &field_rev.field_type).data;
Some(Cell::new(field_id, data))
}
pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc<RowRevision>]) -> Vec<RowOrder> { pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc<RowRevision>]) -> Vec<RowOrder> {
row_revs.iter().map(RowOrder::from).collect::<Vec<_>>() row_revs.iter().map(RowOrder::from).collect::<Vec<_>>()
} }

View File

@ -1,10 +1,7 @@
use flowy_grid::services::field::*; use flowy_grid::services::field::*;
use flowy_grid::services::grid_editor::{GridPadBuilder, GridRevisionEditor};
use flowy_grid::services::row::CreateRowRevisionPayload;
use flowy_grid::services::setting::GridSettingChangesetBuilder;
use flowy_grid_data_model::entities::*; use flowy_grid_data_model::entities::*;
use flowy_grid_data_model::revision::*; use flowy_grid_data_model::revision::*;
use flowy_sync::client_grid::GridBuilder;
pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) { pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
let field_rev = FieldBuilder::new(RichTextTypeOptionBuilder::default()) let field_rev = FieldBuilder::new(RichTextTypeOptionBuilder::default())

View File

@ -1,9 +1,6 @@
use crate::grid::script::EditorScript::*; use crate::grid::script::EditorScript::*;
use crate::grid::script::*; use crate::grid::script::*;
use flowy_grid_data_model::entities::{CreateGridFilterPayload, TextFilterCondition};
use flowy_grid_data_model::entities::{
CreateGridFilterParams, CreateGridFilterPayload, GridLayoutType, GridSettingChangesetParams, TextFilterCondition,
};
#[tokio::test] #[tokio::test]
async fn grid_filter_create_test() { async fn grid_filter_create_test() {

View File

@ -6,11 +6,9 @@ use chrono::NaiveDateTime;
use flowy_grid::services::field::{ use flowy_grid::services::field::{
DateCellData, MultiSelectTypeOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, DateCellData, MultiSelectTypeOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR,
}; };
use flowy_grid::services::row::{ use flowy_grid::services::row::{decode_cell_data, CreateRowRevisionBuilder};
decode_cell_data_from_type_option_cell_data, CreateRowRevisionBuilder, CreateRowRevisionPayload,
};
use flowy_grid_data_model::entities::FieldType; use flowy_grid_data_model::entities::FieldType;
use flowy_grid_data_model::revision::{FieldRevision, RowMetaChangeset}; use flowy_grid_data_model::revision::RowMetaChangeset;
#[tokio::test] #[tokio::test]
async fn grid_create_row_count_test() { async fn grid_create_row_count_test() {
@ -139,7 +137,7 @@ async fn grid_row_add_date_cell_test() {
let date_field = date_field.unwrap(); let date_field = date_field.unwrap();
let cell_data = context.cell_by_field_id.get(&date_field.id).unwrap().clone(); let cell_data = context.cell_by_field_id.get(&date_field.id).unwrap().clone();
assert_eq!( assert_eq!(
decode_cell_data_from_type_option_cell_data(cell_data.data.clone(), &date_field, &date_field.field_type) decode_cell_data(cell_data.data.clone(), &date_field)
.parse::<DateCellData>() .parse::<DateCellData>()
.unwrap() .unwrap()
.date, .date,

View File

@ -53,12 +53,13 @@ impl<'a> GridRowTestBuilder<'a> {
self self
} }
pub fn field_rev_with_type(&self, field_type: &FieldType) -> &FieldRevision { pub fn field_rev_with_type(&self, field_type: &FieldType) -> FieldRevision {
self.test self.test
.field_revs .field_revs
.iter() .iter()
.find(|field_rev| field_rev.field_type == &field_type) .find(|field_rev| &field_rev.field_type == field_type)
.unwrap() .unwrap()
.clone()
} }
pub fn build(self) -> CreateRowRevisionPayload { pub fn build(self) -> CreateRowRevisionPayload {

View File

@ -11,7 +11,7 @@ protobuf = {version = "2.18.0"}
bytes = "1.0" bytes = "1.0"
strum = "0.21" strum = "0.21"
strum_macros = "0.21" strum_macros = "0.21"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = {version = "1.0"} serde_json = {version = "1.0"}
serde_repr = "0.1" serde_repr = "0.1"
nanoid = "0.4.0" nanoid = "0.4.0"

View File

@ -125,9 +125,9 @@ pub enum TextFilterCondition {
TextIsEmpty = 6, TextIsEmpty = 6,
TextIsNotEmpty = 7, TextIsNotEmpty = 7,
} }
impl std::convert::Into<i32> for TextFilterCondition { impl std::convert::From<TextFilterCondition> for i32 {
fn into(self) -> i32 { fn from(value: TextFilterCondition) -> Self {
self as i32 value as i32
} }
} }
@ -190,9 +190,9 @@ impl std::default::Default for NumberFilterCondition {
} }
} }
impl std::convert::Into<i32> for NumberFilterCondition { impl std::convert::From<NumberFilterCondition> for i32 {
fn into(self) -> i32 { fn from(value: NumberFilterCondition) -> Self {
self as i32 value as i32
} }
} }
impl std::convert::TryFrom<u8> for NumberFilterCondition { impl std::convert::TryFrom<u8> for NumberFilterCondition {
@ -240,9 +240,9 @@ pub enum SelectOptionCondition {
OptionIsNotEmpty = 3, OptionIsNotEmpty = 3,
} }
impl std::convert::Into<i32> for SelectOptionCondition { impl std::convert::From<SelectOptionCondition> for i32 {
fn into(self) -> i32 { fn from(value: SelectOptionCondition) -> Self {
self as i32 value as i32
} }
} }

View File

@ -30,9 +30,9 @@ pub fn gen_field_id() -> String {
pub struct GridRevision { pub struct GridRevision {
pub grid_id: String, pub grid_id: String,
pub fields: Vec<FieldRevision>, pub fields: Vec<FieldRevision>,
pub blocks: Vec<GridBlockRevision>, pub blocks: Vec<Arc<GridBlockRevision>>,
#[serde(default, skip)] #[serde(default)]
pub setting: GridSettingRevision, pub setting: GridSettingRevision,
} }
@ -45,6 +45,15 @@ impl GridRevision {
setting: GridSettingRevision::default(), setting: GridSettingRevision::default(),
} }
} }
pub fn from_build_context(grid_id: &str, context: BuildGridContext) -> Self {
Self {
grid_id: grid_id.to_owned(),
fields: context.field_revs,
blocks: context.blocks.into_iter().map(Arc::new).collect(),
setting: Default::default(),
}
}
} }
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -17,6 +17,8 @@ pub fn gen_grid_sort_id() -> String {
#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct GridSettingRevision { pub struct GridSettingRevision {
pub layout: GridLayoutRevision,
#[serde(with = "indexmap::serde_seq")] #[serde(with = "indexmap::serde_seq")]
pub filter: IndexMap<GridLayoutRevision, Vec<GridFilterRevision>>, pub filter: IndexMap<GridLayoutRevision, Vec<GridFilterRevision>>,

View File

@ -35,7 +35,7 @@ impl GridRevisionPad {
.blocks .blocks
.iter() .iter()
.map(|block| { .map(|block| {
let mut duplicated_block = block.clone(); let mut duplicated_block = (&*block.clone()).clone();
duplicated_block.block_id = gen_block_id(); duplicated_block.block_id = gen_block_id();
duplicated_block duplicated_block
}) })
@ -288,7 +288,7 @@ impl GridRevisionPad {
Ok(None) Ok(None)
} else { } else {
match grid_meta.blocks.last() { match grid_meta.blocks.last() {
None => grid_meta.blocks.push(block), None => grid_meta.blocks.push(Arc::new(block)),
Some(last_block) => { Some(last_block) => {
if last_block.start_row_index > block.start_row_index if last_block.start_row_index > block.start_row_index
&& last_block.len() > block.start_row_index && last_block.len() > block.start_row_index
@ -296,7 +296,7 @@ impl GridRevisionPad {
let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string(); let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string();
return Err(CollaborateError::internal().context(msg)) return Err(CollaborateError::internal().context(msg))
} }
grid_meta.blocks.push(block); grid_meta.blocks.push(Arc::new(block));
} }
} }
Ok(Some(())) Ok(Some(()))
@ -304,7 +304,7 @@ impl GridRevisionPad {
}) })
} }
pub fn get_block_revs(&self) -> Vec<GridBlockRevision> { pub fn get_block_revs(&self) -> Vec<Arc<GridBlockRevision>> {
self.grid_rev.blocks.clone() self.grid_rev.blocks.clone()
} }
@ -362,7 +362,9 @@ impl GridRevisionPad {
if let Some(delete_filter_id) = changeset.delete_filter { if let Some(delete_filter_id) = changeset.delete_filter {
match grid_rev.setting.filter.get_mut(&layout_rev) { match grid_rev.setting.filter.get_mut(&layout_rev) {
Some(filters) => filters.retain(|filter| filter.id != delete_filter_id), Some(filters) => filters.retain(|filter| filter.id != delete_filter_id),
None => {} None => {
tracing::warn!("Can't find the filter with {:?}", layout_rev);
}
} }
} }
if let Some(params) = changeset.insert_group { if let Some(params) = changeset.insert_group {
@ -384,7 +386,9 @@ impl GridRevisionPad {
if let Some(delete_group_id) = changeset.delete_group { if let Some(delete_group_id) = changeset.delete_group {
match grid_rev.setting.group.get_mut(&layout_rev) { match grid_rev.setting.group.get_mut(&layout_rev) {
Some(groups) => groups.retain(|group| group.id != delete_group_id), Some(groups) => groups.retain(|group| group.id != delete_group_id),
None => {} None => {
tracing::warn!("Can't find the group with {:?}", layout_rev);
}
} }
} }
if let Some(sort) = changeset.insert_sort { if let Some(sort) = changeset.insert_sort {
@ -405,7 +409,9 @@ impl GridRevisionPad {
if let Some(delete_sort_id) = changeset.delete_sort { if let Some(delete_sort_id) = changeset.delete_sort {
match grid_rev.setting.sort.get_mut(&layout_rev) { match grid_rev.setting.sort.get_mut(&layout_rev) {
Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id), Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id),
None => {} None => {
tracing::warn!("Can't find the sort with {:?}", layout_rev);
}
} }
} }
Ok(is_changed) Ok(is_changed)
@ -459,7 +465,10 @@ impl GridRevisionPad {
tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id); tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id);
Ok(None) Ok(None)
} }
Some(index) => f(&mut grid_rev.blocks[index]), Some(index) => {
let block_rev = Arc::make_mut(&mut grid_rev.blocks[index]);
f(block_rev)
}
}, },
) )
} }