appflowy преди 3 години
родител
ревизия
d101509b32

+ 3 - 3
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -24,7 +24,7 @@ pub(crate) async fn get_rows_handler(
 ) -> DataResult<RepeatedRow, FlowyError> {
     let payload: QueryRowPayload = data.into_inner();
     let editor = manager.get_grid_editor(&payload.grid_id)?;
-    let repeated_row: RepeatedRow = editor.get_rows(Some(payload.row_orders)).await?.into();
+    let repeated_row: RepeatedRow = editor.get_rows(payload.row_orders).await?.into();
     data_result(repeated_row)
 }
 
@@ -50,10 +50,10 @@ pub(crate) async fn create_row_handler(
     Ok(())
 }
 
-#[tracing::instrument(level = "debug", skip(data, manager), err)]
+#[tracing::instrument(level = "debug", skip_all, err)]
 pub(crate) async fn update_cell_handler(
     data: Data<Cell>,
-    manager: AppData<Arc<GridManager>>,
+    _manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
     let _cell: Cell = data.into_inner();
     // let editor = manager.get_grid_editor(id.as_ref())?;

+ 1 - 1
frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs

@@ -2,7 +2,7 @@ use crate::services::field::{
     CheckboxDescription, DateDescription, DateFormat, MoneySymbol, MultiSelectDescription, NumberDescription,
     RichTextDescription, SelectOption, SingleSelectDescription, TimeFormat,
 };
-use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
+use flowy_grid_data_model::entities::{Field, FieldType};
 
 pub struct FieldBuilder {
     field: Field,

+ 33 - 46
frontend/rust-lib/flowy-grid/src/services/field/type_options.rs

@@ -2,12 +2,12 @@
 use crate::impl_from_and_to_type_option;
 use crate::services::row::StringifyCellData;
 use crate::services::util::*;
-use bytes::Bytes;
+
 use chrono::format::strftime::StrftimeItems;
 use chrono::NaiveDateTime;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
+use flowy_grid_data_model::entities::{Field, FieldType};
 use rust_decimal::Decimal;
 use rusty_money::{
     iso::{Currency, CNY, EUR, USD},
@@ -25,12 +25,12 @@ pub struct RichTextDescription {
 impl_from_and_to_type_option!(RichTextDescription, FieldType::RichText);
 
 impl StringifyCellData for RichTextDescription {
-    fn str_from_cell_data(&self, data: AnyData) -> String {
-        data.to_string()
+    fn str_from_cell_data(&self, data: String) -> String {
+        data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
-        Ok(AnyData::from_str(self.field_type(), s))
+    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
+        Ok(s.to_owned())
     }
 }
 
@@ -43,16 +43,16 @@ pub struct CheckboxDescription {
 impl_from_and_to_type_option!(CheckboxDescription, FieldType::Checkbox);
 
 impl StringifyCellData for CheckboxDescription {
-    fn str_from_cell_data(&self, data: AnyData) -> String {
-        data.to_string()
+    fn str_from_cell_data(&self, data: String) -> String {
+        data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
+    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
         let s = match string_to_bool(s) {
             true => "1",
             false => "0",
         };
-        Ok(AnyData::from_str(self.field_type(), s))
+        Ok(s.to_owned())
     }
 }
 
@@ -89,30 +89,24 @@ impl DateDescription {
 }
 
 impl StringifyCellData for DateDescription {
-    fn str_from_cell_data(&self, data: AnyData) -> String {
-        match String::from_utf8(data.value) {
-            Ok(s) => match s.parse::<i64>() {
-                Ok(timestamp) => {
-                    let native = NaiveDateTime::from_timestamp(timestamp, 0);
-                    self.today_from_native(native)
-                }
-                Err(e) => {
-                    tracing::debug!("DateDescription format {} fail. error: {:?}", s, e);
-                    String::new()
-                }
-            },
+    fn str_from_cell_data(&self, data: String) -> String {
+        match data.parse::<i64>() {
+            Ok(timestamp) => {
+                let native = NaiveDateTime::from_timestamp(timestamp, 0);
+                self.today_from_native(native)
+            }
             Err(e) => {
-                tracing::error!("DateDescription stringify any_data failed. {:?}", e);
+                tracing::debug!("DateDescription format {} fail. error: {:?}", data, e);
                 String::new()
             }
         }
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
+    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
         let timestamp = s
             .parse::<i64>()
             .map_err(|e| FlowyError::internal().context(format!("Parse {} to i64 failed: {}", s, e)))?;
-        Ok(AnyData::from_str(self.field_type(), &format!("{}", timestamp)))
+        Ok(format!("{}", timestamp))
     }
 }
 
@@ -210,12 +204,12 @@ pub struct SingleSelectDescription {
 impl_from_and_to_type_option!(SingleSelectDescription, FieldType::SingleSelect);
 
 impl StringifyCellData for SingleSelectDescription {
-    fn str_from_cell_data(&self, data: AnyData) -> String {
-        data.to_string()
+    fn str_from_cell_data(&self, data: String) -> String {
+        data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
-        Ok(AnyData::from_str(self.field_type(), s))
+    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
+        Ok(s.to_owned())
     }
 }
 
@@ -230,12 +224,12 @@ pub struct MultiSelectDescription {
 }
 impl_from_and_to_type_option!(MultiSelectDescription, FieldType::MultiSelect);
 impl StringifyCellData for MultiSelectDescription {
-    fn str_from_cell_data(&self, data: AnyData) -> String {
-        data.to_string()
+    fn str_from_cell_data(&self, data: String) -> String {
+        data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
-        Ok(AnyData::from_str(self.field_type(), s))
+    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
+        Ok(s.to_owned())
     }
 }
 
@@ -322,24 +316,17 @@ impl NumberDescription {
 }
 
 impl StringifyCellData for NumberDescription {
-    fn str_from_cell_data(&self, data: AnyData) -> String {
-        match String::from_utf8(data.value) {
-            Ok(s) => match self.money_from_str(&s) {
-                Some(money_str) => money_str,
-                None => String::default(),
-            },
-            Err(e) => {
-                tracing::error!("NumberDescription stringify any_data failed. {:?}", e);
-                String::new()
-            }
+    fn str_from_cell_data(&self, data: String) -> String {
+        match self.money_from_str(&data) {
+            Some(money_str) => money_str,
+            None => String::default(),
         }
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
+    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
         let strip_symbol_money = strip_money_symbol(s);
         let decimal = Decimal::from_str(&strip_symbol_money).map_err(|err| FlowyError::internal().context(err))?;
-        let money_str = decimal.to_string();
-        Ok(AnyData::from_str(self.field_type(), &money_str))
+        Ok(decimal.to_string())
     }
 }
 

+ 19 - 16
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -1,7 +1,7 @@
 use crate::manager::GridUser;
 use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
 
-use crate::services::grid_meta_editor::{ClientGridBlockMetaEditor, GridBlockMetaEditorManager};
+use crate::services::grid_meta_editor::GridBlockMetaEditorManager;
 use bytes::Bytes;
 use dashmap::DashMap;
 use flowy_collaboration::client_grid::{GridChange, GridMetaPad};
@@ -9,13 +9,10 @@ use flowy_collaboration::entities::revision::Revision;
 use flowy_collaboration::util::make_delta_from_revisions;
 use flowy_error::{FlowyError, FlowyResult};
 use flowy_grid_data_model::entities::{
-    Field, FieldChangeset, Grid, GridBlock, GridBlockChangeset, RepeatedField, RepeatedFieldOrder, RepeatedRow,
-    RepeatedRowOrder, Row,
-};
-use flowy_sync::disk::SQLiteGridBlockMetaRevisionPersistence;
-use flowy_sync::{
-    RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
+    Field, FieldChangeset, Grid, GridBlock, GridBlockChangeset, RepeatedFieldOrder, RepeatedRowOrder, Row,
 };
+
+use flowy_sync::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
 use lib_infra::future::FutureResult;
 use lib_ot::core::PlainTextAttributes;
 use std::sync::Arc;
@@ -83,23 +80,29 @@ impl ClientGridEditor {
 
     pub async fn create_row(&self) -> FlowyResult<()> {
         let fields = self.grid_meta_pad.read().await.get_fields(None)?;
-        match self.grid_meta_pad.read().await.get_blocks().last() {
+        let grid_block = match self.grid_meta_pad.read().await.get_blocks().last() {
             None => Err(FlowyError::internal().context("There is no grid block in this grid")),
-            Some(grid_block) => {
-                let row_count = self.block_meta_manager.create_row(fields, grid_block).await?;
-                let change = GridBlockChangeset::from_row_count(&grid_block.id, row_count);
-                let _ = self.update_block(change).await?;
-                Ok(())
-            }
-        }
+            Some(grid_block) => Ok(grid_block.clone()),
+        }?;
+
+        let row_count = self.block_meta_manager.create_row(fields, &grid_block).await?;
+        let change = GridBlockChangeset::from_row_count(&grid_block.id, row_count);
+        let _ = self.update_block(change).await?;
+        Ok(())
     }
 
-    pub async fn get_rows(&self, row_orders: Option<RepeatedRowOrder>) -> FlowyResult<Vec<Row>> {
+    pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> FlowyResult<Vec<Row>> {
         let fields = self.grid_meta_pad.read().await.get_fields(None)?;
         let rows = self.block_meta_manager.get_rows(fields, row_orders).await?;
         Ok(rows)
     }
 
+    pub async fn get_all_rows(&self) -> FlowyResult<Vec<Row>> {
+        let fields = self.grid_meta_pad.read().await.get_fields(None)?;
+        let grid_blocks = self.grid_meta_pad.read().await.get_blocks();
+        self.block_meta_manager.get_all_rows(grid_blocks, fields).await
+    }
+
     pub async fn delete_rows(&self, row_orders: Option<RepeatedRowOrder>) -> FlowyResult<()> {
         let row_counts = self.block_meta_manager.delete_rows(row_orders).await?;
         for (block_id, row_count) in row_counts {

+ 36 - 31
frontend/rust-lib/flowy-grid/src/services/grid_meta_editor.rs

@@ -1,22 +1,20 @@
 use crate::manager::GridUser;
-use crate::services::row::{make_row_ids_per_block, make_rows, sort_rows, RowBuilder};
+use crate::services::row::{make_row_by_row_id, make_row_ids_per_block, make_rows, RowBuilder};
 use bytes::Bytes;
-use dashmap::mapref::one::Ref;
+
 use dashmap::DashMap;
 use flowy_collaboration::client_grid::{GridBlockMetaChange, GridBlockMetaPad};
 use flowy_collaboration::entities::revision::Revision;
 use flowy_collaboration::util::make_delta_from_revisions;
 use flowy_error::{FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::{
-    Field, GridBlock, RepeatedRow, RepeatedRowOrder, Row, RowMeta, RowMetaChangeset,
-};
+use flowy_grid_data_model::entities::{Field, GridBlock, RepeatedRowOrder, Row, RowMeta, RowMetaChangeset};
 use flowy_sync::disk::SQLiteGridBlockMetaRevisionPersistence;
 use flowy_sync::{
     RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
 };
 use lib_infra::future::FutureResult;
 use lib_ot::core::PlainTextAttributes;
-use lib_sqlite::ConnectionPool;
+
 use std::collections::HashMap;
 use std::sync::Arc;
 use tokio::sync::RwLock;
@@ -52,32 +50,34 @@ impl GridBlockMetaEditorManager {
         editor.create_row(row).await
     }
 
-    pub(crate) async fn delete_rows(&self, row_orders: Option<RepeatedRowOrder>) -> FlowyResult<Vec<(String, i32)>> {
+    pub(crate) async fn delete_rows(&self, _row_orders: Option<RepeatedRowOrder>) -> FlowyResult<Vec<(String, i32)>> {
         Ok(vec![("".to_owned(), 2)])
     }
 
-    pub(crate) async fn get_rows(
-        &self,
-        fields: Vec<Field>,
-        row_orders: Option<RepeatedRowOrder>,
-    ) -> FlowyResult<Vec<Row>> {
-        match row_orders {
-            None => {
-                let rows = vec![];
-                Ok(rows)
-            }
-            Some(row_orders) => {
-                let row_ids_per_blocks = make_row_ids_per_block(&row_orders);
-                let mut rows = vec![];
-                for row_ids_per_block in row_ids_per_blocks {
-                    let editor = self.get_editor(&row_ids_per_block.block_id).await?;
-                    let row_metas = editor.get_rows(row_ids_per_block.row_ids).await?;
-                    rows.extend(make_rows(&fields, row_metas));
-                }
-                sort_rows(&mut rows, row_orders);
-                Ok(rows)
-            }
+    pub(crate) async fn get_all_rows(&self, grid_blocks: Vec<GridBlock>, fields: Vec<Field>) -> FlowyResult<Vec<Row>> {
+        let mut rows = vec![];
+        for grid_block in grid_blocks {
+            let editor = self.get_editor(&grid_block.id).await?;
+            let row_metas = editor.get_rows(None).await?;
+            rows.extend(make_rows(&fields, row_metas));
+        }
+        Ok(rows)
+    }
+
+    pub(crate) async fn get_rows(&self, fields: Vec<Field>, row_orders: RepeatedRowOrder) -> FlowyResult<Vec<Row>> {
+        let row_ids_per_blocks = make_row_ids_per_block(&row_orders);
+        let mut row_map: HashMap<String, Row> = HashMap::new();
+        for row_ids_per_block in row_ids_per_blocks {
+            let editor = self.get_editor(&row_ids_per_block.block_id).await?;
+            let row_metas = editor.get_rows(Some(row_ids_per_block.row_ids)).await?;
+            row_map.extend(make_row_by_row_id(&fields, row_metas));
         }
+
+        let rows = row_orders
+            .iter()
+            .flat_map(|row_order| row_map.remove(&row_order.row_id))
+            .collect::<Vec<_>>();
+        Ok(rows)
     }
 }
 
@@ -158,9 +158,14 @@ impl ClientGridBlockMetaEditor {
         Ok(())
     }
 
-    pub async fn get_rows(&self, row_ids: Vec<String>) -> FlowyResult<Vec<RowMeta>> {
-        let rows = self.meta_pad.read().await.get_rows(row_ids)?;
-        Ok(rows)
+    pub async fn get_rows(&self, row_ids: Option<Vec<String>>) -> FlowyResult<Vec<RowMeta>> {
+        match row_ids {
+            None => Ok(self.meta_pad.read().await.all_rows()),
+            Some(row_ids) => {
+                let rows = self.meta_pad.read().await.get_rows(row_ids)?;
+                Ok(rows)
+            }
+        }
     }
 
     async fn modify<F>(&self, f: F) -> FlowyResult<()>

+ 7 - 7
frontend/rust-lib/flowy-grid/src/services/row/cell_stringify.rs

@@ -1,15 +1,15 @@
 use crate::services::field::*;
-use crate::services::util::*;
+
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
+use flowy_grid_data_model::entities::{Field, FieldType};
 
 pub trait StringifyCellData {
-    fn str_from_cell_data(&self, data: AnyData) -> String;
-    fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError>;
+    fn str_from_cell_data(&self, data: String) -> String;
+    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError>;
 }
 
 #[allow(dead_code)]
-pub fn stringify_serialize(field: &Field, s: &str) -> Result<AnyData, FlowyError> {
+pub fn stringify_serialize(field: &Field, s: &str) -> Result<String, FlowyError> {
     match field.field_type {
         FieldType::RichText => RichTextDescription::from(field).str_to_cell_data(s),
         FieldType::Number => NumberDescription::from(field).str_to_cell_data(s),
@@ -20,8 +20,8 @@ pub fn stringify_serialize(field: &Field, s: &str) -> Result<AnyData, FlowyError
     }
 }
 
-pub(crate) fn stringify_deserialize(data: AnyData, field: &Field) -> Result<String, FlowyError> {
-    let _ = check_type_id(&data, field)?;
+pub(crate) fn stringify_deserialize(data: String, field: &Field) -> Result<String, FlowyError> {
+    // let _ = check_type_id(&data, field)?;
     let s = match field.field_type {
         FieldType::RichText => RichTextDescription::from(field).str_from_cell_data(data),
         FieldType::Number => NumberDescription::from(field).str_from_cell_data(data),

+ 1 - 1
frontend/rust-lib/flowy-grid/src/services/row/mod.rs

@@ -4,4 +4,4 @@ mod row_loader;
 
 pub use cell_stringify::*;
 pub use row_builder::*;
-pub use row_loader::*;
+pub(crate) use row_loader::*;

+ 64 - 45
frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs

@@ -1,4 +1,6 @@
-use flowy_grid_data_model::entities::{Field, RepeatedRowOrder, Row, RowMeta};
+use crate::services::row::stringify_deserialize;
+use flowy_grid_data_model::entities::{Cell, CellMeta, Field, RepeatedRowOrder, Row, RowMeta};
+use rayon::iter::{IntoParallelIterator, ParallelIterator};
 use std::collections::HashMap;
 
 pub(crate) struct RowIdsPerBlock {
@@ -19,50 +21,67 @@ pub(crate) fn make_row_ids_per_block(row_orders: &RepeatedRowOrder) -> Vec<RowId
     map.into_values().collect::<Vec<_>>()
 }
 
-pub(crate) fn sort_rows(rows: &mut Vec<Row>, row_orders: RepeatedRowOrder) {
-    todo!()
+pub(crate) fn make_rows(fields: &Vec<Field>, row_metas: Vec<RowMeta>) -> Vec<Row> {
+    let field_map = fields
+        .iter()
+        .map(|field| (&field.id, field))
+        .collect::<HashMap<&String, &Field>>();
+
+    let make_row = |row_meta: RowMeta| {
+        let cell_by_field_id = row_meta
+            .cell_by_field_id
+            .into_par_iter()
+            .flat_map(|(field_id, raw_cell)| make_cell(&field_map, field_id, raw_cell))
+            .collect::<HashMap<String, Cell>>();
+
+        Row {
+            id: row_meta.id.clone(),
+            cell_by_field_id,
+            height: row_meta.height,
+        }
+    };
+
+    row_metas.into_iter().map(make_row).collect::<Vec<Row>>()
+}
+
+#[inline(always)]
+fn make_cell(field_map: &HashMap<&String, &Field>, field_id: String, raw_cell: CellMeta) -> Option<(String, Cell)> {
+    let field = field_map.get(&field_id)?;
+    match stringify_deserialize(raw_cell.data, field) {
+        Ok(content) => {
+            let cell = Cell::new(&field_id, content);
+            Some((field_id, cell))
+        }
+        Err(e) => {
+            tracing::error!("{}", e);
+            None
+        }
+    }
 }
 
-pub(crate) fn make_rows(fields: &Vec<Field>, rows: Vec<RowMeta>) -> Vec<Row> {
-    // let make_cell = |field_id: String, raw_cell: CellMeta| {
-    //     let some_field = self.field_map.get(&field_id);
-    //     if some_field.is_none() {
-    //         tracing::error!("Can't find the field with {}", field_id);
-    //         return None;
-    //     }
-    //     self.cell_map.insert(raw_cell.id.clone(), raw_cell.clone());
-    //
-    //     let field = some_field.unwrap();
-    //     match stringify_deserialize(raw_cell.data, field.value()) {
-    //         Ok(content) => {
-    //             let cell = Cell {
-    //                 id: raw_cell.id,
-    //                 field_id: field_id.clone(),
-    //                 content,
-    //             };
-    //             Some((field_id, cell))
-    //         }
-    //         Err(_) => None,
-    //     }
-    // };
-    //
-    // let rows = row_metas
-    //     .into_par_iter()
-    //     .map(|row_meta| {
-    //         let mut row = Row {
-    //             id: row_meta.id.clone(),
-    //             cell_by_field_id: Default::default(),
-    //             height: row_meta.height,
-    //         };
-    //         row.cell_by_field_id = row_meta
-    //             .cell_by_field_id
-    //             .into_par_iter()
-    //             .flat_map(|(field_id, raw_cell)| make_cell(field_id, raw_cell))
-    //             .collect::<HashMap<String, Cell>>();
-    //         row
-    //     })
-    //     .collect::<Vec<Row>>();
-    //
-    // Ok(rows.into())
-    todo!()
+pub(crate) fn make_row_by_row_id(fields: &Vec<Field>, row_metas: Vec<RowMeta>) -> HashMap<String, Row> {
+    let field_map = fields
+        .iter()
+        .map(|field| (&field.id, field))
+        .collect::<HashMap<&String, &Field>>();
+
+    let make_row = |row_meta: RowMeta| {
+        let cell_by_field_id = row_meta
+            .cell_by_field_id
+            .into_par_iter()
+            .flat_map(|(field_id, raw_cell)| make_cell(&field_map, field_id, raw_cell))
+            .collect::<HashMap<String, Cell>>();
+
+        let row = Row {
+            id: row_meta.id.clone(),
+            cell_by_field_id,
+            height: row_meta.height,
+        };
+        (row.id.clone(), row)
+    };
+
+    row_metas
+        .into_par_iter()
+        .map(make_row)
+        .collect::<HashMap<String, Row>>()
 }

+ 1 - 1
frontend/rust-lib/flowy-grid/src/util.rs

@@ -1,6 +1,6 @@
 use crate::services::field::*;
 use flowy_collaboration::client_grid::{BuildGridInfo, GridBuilder};
-use flowy_grid_data_model::entities::{Field, FieldType};
+use flowy_grid_data_model::entities::FieldType;
 
 pub fn make_default_grid(grid_id: &str) -> BuildGridInfo {
     let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::new())

+ 1 - 1
frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs

@@ -169,6 +169,6 @@ async fn grid_update_block() {
 
 #[tokio::test]
 async fn grid_create_row() {
-    let scripts = vec![AssertRowCount(2), CreateRow, CreateRow, CreateRow, AssertRowCount(5)];
+    let scripts = vec![AssertRowCount(3), CreateRow, CreateRow, AssertRowCount(5)];
     GridEditorTest::new().await.run_scripts(scripts).await;
 }

+ 3 - 3
frontend/rust-lib/flowy-grid/tests/grid/script.rs

@@ -1,8 +1,8 @@
 use flowy_grid::services::field::*;
 use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder};
-use flowy_grid_data_model::entities::{AnyData, Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset};
+use flowy_grid_data_model::entities::{Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset};
 use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS;
-use flowy_test::event_builder::FolderEventBuilder;
+
 use flowy_test::helper::ViewTest;
 use flowy_test::FlowySDKTest;
 use std::sync::Arc;
@@ -89,7 +89,7 @@ impl GridEditorTest {
                 self.editor.create_row().await.unwrap();
             }
             EditorScript::AssertRowCount(count) => {
-                assert_eq!(self.editor.get_rows(None).await.unwrap().len(), count);
+                assert_eq!(self.editor.get_all_rows().await.unwrap().len(), count);
             }
             EditorScript::AssertGridMetaPad => {
                 sleep(Duration::from_millis(2 * REVISION_WRITE_INTERVAL_IN_MILLIS)).await;

+ 5 - 1
shared-lib/flowy-collaboration/src/client_grid/block_pad.rs

@@ -1,5 +1,5 @@
 use crate::entities::revision::{md5, RepeatedRevision, Revision};
-use crate::errors::{internal_error, CollaborateError, CollaborateResult};
+use crate::errors::{CollaborateError, CollaborateResult};
 use crate::util::{cal_diff, make_delta_from_revisions};
 use flowy_grid_data_model::entities::{GridBlockMeta, RowMeta, RowMetaChangeset};
 use lib_infra::uuid;
@@ -69,6 +69,10 @@ impl GridBlockMetaPad {
             .collect::<Vec<RowMeta>>())
     }
 
+    pub fn all_rows(&self) -> Vec<RowMeta> {
+        self.rows.iter().map(|row| (**row).clone()).collect::<Vec<_>>()
+    }
+
     pub fn number_of_rows(&self) -> i32 {
         self.rows.len() as i32
     }

+ 1 - 1
shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs

@@ -1,6 +1,6 @@
 use crate::client_grid::{make_block_meta_delta, make_grid_delta, GridBlockMetaDelta, GridMetaDelta};
 use crate::errors::{CollaborateError, CollaborateResult};
-use flowy_grid_data_model::entities::{Field, FieldType, GridBlock, GridBlockMeta, GridMeta, RowMeta};
+use flowy_grid_data_model::entities::{Field, GridBlock, GridBlockMeta, GridMeta, RowMeta};
 
 pub struct GridBuilder {
     grid_id: String,

+ 3 - 3
shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs

@@ -2,7 +2,7 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision};
 use crate::errors::{internal_error, CollaborateError, CollaborateResult};
 use crate::util::{cal_diff, make_delta_from_revisions};
 use flowy_grid_data_model::entities::{
-    Field, FieldChangeset, GridBlock, GridBlockChangeset, GridMeta, RepeatedField, RepeatedFieldOrder,
+    Field, FieldChangeset, GridBlock, GridBlockChangeset, GridMeta, RepeatedFieldOrder,
 };
 use lib_infra::uuid;
 use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
@@ -58,7 +58,7 @@ impl GridMetaPad {
 
     pub fn get_fields(&self, field_orders: Option<RepeatedFieldOrder>) -> CollaborateResult<Vec<Field>> {
         match field_orders {
-            None => Ok(self.grid_meta.fields.clone().into()),
+            None => Ok(self.grid_meta.fields.clone()),
             Some(field_orders) => {
                 let field_by_field_id = self
                     .grid_meta
@@ -127,7 +127,7 @@ impl GridMetaPad {
 
     pub fn create_block(&mut self, block: GridBlock) -> CollaborateResult<Option<GridChange>> {
         self.modify_grid(|grid| {
-            if grid.blocks.iter().find(|b| b.id == block.id).is_some() {
+            if grid.blocks.iter().any(|b| b.id == block.id) {
                 tracing::warn!("Duplicate grid block");
                 Ok(None)
             } else {

+ 9 - 0
shared-lib/flowy-grid-data-model/src/entities/grid.rs

@@ -123,6 +123,15 @@ pub struct Cell {
     pub content: String,
 }
 
+impl Cell {
+    pub fn new(field_id: &str, content: String) -> Self {
+        Self {
+            field_id: field_id.to_owned(),
+            content,
+        }
+    }
+}
+
 #[derive(ProtoBuf, Default)]
 pub struct CreateGridPayload {
     #[pb(index = 1)]

+ 4 - 4
shared-lib/flowy-grid-data-model/src/entities/meta.rs

@@ -175,13 +175,13 @@ impl std::default::Default for FieldType {
 
 impl AsRef<FieldType> for FieldType {
     fn as_ref(&self) -> &FieldType {
-        &self
+        self
     }
 }
 
-impl Into<FieldType> for &FieldType {
-    fn into(self) -> FieldType {
-        self.clone()
+impl From<&FieldType> for FieldType {
+    fn from(field: &FieldType) -> Self {
+        field.clone()
     }
 }