mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add row test
This commit is contained in:
parent
572e38ec1c
commit
d101509b32
@ -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())?;
|
||||
|
@ -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,
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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<()>
|
||||
|
@ -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),
|
||||
|
@ -4,4 +4,4 @@ mod row_loader;
|
||||
|
||||
pub use cell_stringify::*;
|
||||
pub use row_builder::*;
|
||||
pub use row_loader::*;
|
||||
pub(crate) use row_loader::*;
|
||||
|
@ -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>>()
|
||||
}
|
||||
|
||||
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!()
|
||||
#[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_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,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())
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,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,
|
||||
|
@ -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 {
|
||||
|
@ -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)]
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user