mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: create default grid
This commit is contained in:
parent
df399d3f35
commit
6579940dc8
@ -20,7 +20,7 @@ class View extends $pb.GeneratedMessage {
|
||||
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'belongToId')
|
||||
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
|
||||
..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
|
||||
..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.Block, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
|
||||
..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.TextBlock, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
|
||||
..aInt64(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'version')
|
||||
..aOM<RepeatedView>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'belongings', subBuilder: RepeatedView.create)
|
||||
..aInt64(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'modifiedTime')
|
||||
@ -274,7 +274,7 @@ class CreateViewPayload extends $pb.GeneratedMessage {
|
||||
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
|
||||
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
|
||||
..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
|
||||
..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.Block, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
|
||||
..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.TextBlock, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
|
||||
..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData')
|
||||
..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
|
||||
..hasRequiredFields = false
|
||||
@ -408,7 +408,7 @@ class CreateViewParams extends $pb.GeneratedMessage {
|
||||
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
|
||||
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
|
||||
..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
|
||||
..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.Block, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
|
||||
..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.TextBlock, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
|
||||
..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData')
|
||||
..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
|
||||
..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
|
||||
|
@ -10,11 +10,11 @@ import 'dart:core' as $core;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
class ViewDataType extends $pb.ProtobufEnum {
|
||||
static const ViewDataType Block = ViewDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Block');
|
||||
static const ViewDataType TextBlock = ViewDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TextBlock');
|
||||
static const ViewDataType Grid = ViewDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Grid');
|
||||
|
||||
static const $core.List<ViewDataType> values = <ViewDataType> [
|
||||
Block,
|
||||
TextBlock,
|
||||
Grid,
|
||||
];
|
||||
|
||||
|
@ -12,13 +12,13 @@ import 'dart:typed_data' as $typed_data;
|
||||
const ViewDataType$json = const {
|
||||
'1': 'ViewDataType',
|
||||
'2': const [
|
||||
const {'1': 'Block', '2': 0},
|
||||
const {'1': 'TextBlock', '2': 0},
|
||||
const {'1': 'Grid', '2': 1},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `ViewDataType`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List viewDataTypeDescriptor = $convert.base64Decode('CgxWaWV3RGF0YVR5cGUSCQoFQmxvY2sQABIICgRHcmlkEAE=');
|
||||
final $typed_data.Uint8List viewDataTypeDescriptor = $convert.base64Decode('CgxWaWV3RGF0YVR5cGUSDQoJVGV4dEJsb2NrEAASCAoER3JpZBAB');
|
||||
@$core.Deprecated('Use viewDescriptor instead')
|
||||
const View$json = const {
|
||||
'1': 'View',
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::queue::TextBlockRevisionCompactor;
|
||||
use crate::web_socket::{make_block_ws_manager, EditorCommandSender};
|
||||
use crate::{
|
||||
errors::FlowyError,
|
||||
@ -40,7 +39,7 @@ impl ClientTextBlockEditor {
|
||||
rev_web_socket: Arc<dyn RevisionWebSocket>,
|
||||
cloud_service: Arc<dyn RevisionCloudService>,
|
||||
) -> FlowyResult<Arc<Self>> {
|
||||
let document_info = rev_manager.load::<BlockInfoBuilder>(cloud_service).await?;
|
||||
let document_info = rev_manager.load::<TextBlockInfoBuilder>(cloud_service).await?;
|
||||
let delta = document_info.delta()?;
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let doc_id = doc_id.to_string();
|
||||
@ -213,8 +212,8 @@ impl ClientTextBlockEditor {
|
||||
}
|
||||
}
|
||||
|
||||
struct BlockInfoBuilder();
|
||||
impl RevisionObjectBuilder for BlockInfoBuilder {
|
||||
struct TextBlockInfoBuilder();
|
||||
impl RevisionObjectBuilder for TextBlockInfoBuilder {
|
||||
type Output = TextBlockInfo;
|
||||
|
||||
fn build_object(object_id: &str, revisions: Vec<Revision>) -> FlowyResult<Self::Output> {
|
||||
|
@ -11,7 +11,6 @@ use flowy_collaboration::{
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_sync::{DeltaMD5, RevisionCompactor, RevisionManager, RichTextTransformDeltas, TransformDeltas};
|
||||
use futures::stream::StreamExt;
|
||||
use lib_ot::core::{Attributes, Delta};
|
||||
use lib_ot::{
|
||||
core::{Interval, OperationTransformable},
|
||||
rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta},
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::document::edit_script::{EditorScript::*, *};
|
||||
use flowy_collaboration::entities::revision::RevisionState;
|
||||
use flowy_sync::disk::RevisionState;
|
||||
use lib_ot::core::{count_utf16_code_units, Interval};
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use flowy_block::editor::ClientTextBlockEditor;
|
||||
use flowy_block::DOCUMENT_SYNC_INTERVAL_IN_MILLIS;
|
||||
use flowy_collaboration::entities::revision::RevisionState;
|
||||
use flowy_sync::disk::RevisionState;
|
||||
use flowy_test::{helper::ViewTest, FlowySDKTest};
|
||||
use lib_ot::{core::Interval, rich_text::RichTextDelta};
|
||||
use std::sync::Arc;
|
||||
|
@ -12,7 +12,7 @@ use bytes::Bytes;
|
||||
use chrono::Utc;
|
||||
|
||||
use flowy_collaboration::client_document::default::{initial_quill_delta_string, initial_read_me};
|
||||
use flowy_collaboration::entities::revision::RepeatedRevision;
|
||||
|
||||
use flowy_collaboration::{client_folder::FolderPad, entities::ws_data::ServerRevisionWSData};
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_folder_data_model::entities::view::ViewDataType;
|
||||
@ -164,7 +164,7 @@ impl FolderManager {
|
||||
let _ = self.persistence.initialize(user_id, &folder_id).await?;
|
||||
|
||||
let pool = self.persistence.db_pool()?;
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(&user_id, pool));
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(user_id, pool));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), disk_cache));
|
||||
let rev_manager = RevisionManager::new(user_id, folder_id.as_ref(), rev_persistence);
|
||||
|
||||
@ -214,7 +214,7 @@ impl DefaultFolderBuilder {
|
||||
};
|
||||
let _ = view_controller.set_latest_view(&view.id);
|
||||
let _ = view_controller
|
||||
.create_view(&view.id, ViewDataType::Block, Bytes::from(view_data))
|
||||
.create_view(&view.id, ViewDataType::TextBlock, Bytes::from(view_data))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
@ -239,7 +239,7 @@ impl FolderManager {
|
||||
pub trait ViewDataProcessor {
|
||||
fn initialize(&self) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn create_container(&self, view_id: &str, repeated_revision: RepeatedRevision) -> FutureResult<(), FlowyError>;
|
||||
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn delete_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
|
||||
|
||||
@ -247,7 +247,7 @@ pub trait ViewDataProcessor {
|
||||
|
||||
fn delta_str(&self, view_id: &str) -> FutureResult<String, FlowyError>;
|
||||
|
||||
fn default_view_data(&self, view_id: &str) -> String;
|
||||
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<String, FlowyError>;
|
||||
|
||||
fn data_type(&self) -> ViewDataType;
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ use crate::manager::FolderId;
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::util::make_delta_from_revisions;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_sync::disk::RevisionDiskCache;
|
||||
|
||||
use flowy_sync::{
|
||||
RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
|
||||
RevisionWebSocket, RevisionWebSocketManager,
|
||||
RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionWebSocket,
|
||||
RevisionWebSocketManager,
|
||||
};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_ot::core::{Delta, PlainTextAttributes};
|
||||
use lib_sqlite::ConnectionPool;
|
||||
use lib_ot::core::PlainTextAttributes;
|
||||
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -88,7 +88,7 @@ impl FolderMigration {
|
||||
return Ok(None);
|
||||
}
|
||||
let pool = self.database.db_pool()?;
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(&user_id, pool));
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(user_id, pool));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), disk_cache));
|
||||
let (revisions, _) = RevisionLoader {
|
||||
object_id: folder_id.as_ref().to_owned(),
|
||||
|
@ -84,7 +84,7 @@ pub(crate) struct ViewTable {
|
||||
impl ViewTable {
|
||||
pub fn new(view: View) -> Self {
|
||||
let data_type = match view.data_type {
|
||||
ViewDataType::Block => SqlViewDataType::Block,
|
||||
ViewDataType::TextBlock => SqlViewDataType::Block,
|
||||
ViewDataType::Grid => SqlViewDataType::Grid,
|
||||
};
|
||||
|
||||
@ -106,7 +106,7 @@ impl ViewTable {
|
||||
impl std::convert::From<ViewTable> for View {
|
||||
fn from(table: ViewTable) -> Self {
|
||||
let data_type = match table.view_type {
|
||||
SqlViewDataType::Block => ViewDataType::Block,
|
||||
SqlViewDataType::Block => ViewDataType::TextBlock,
|
||||
SqlViewDataType::Grid => ViewDataType::Grid,
|
||||
};
|
||||
|
||||
|
@ -13,10 +13,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::entities::{
|
||||
revision::{RepeatedRevision, Revision},
|
||||
text_block_info::TextBlockId,
|
||||
};
|
||||
use flowy_collaboration::entities::text_block_info::TextBlockId;
|
||||
use flowy_database::kv::KV;
|
||||
use flowy_folder_data_model::entities::view::ViewDataType;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
@ -58,18 +55,18 @@ impl ViewController {
|
||||
#[tracing::instrument(level = "trace", skip(self, params), fields(name = %params.name), err)]
|
||||
pub(crate) async fn create_view_from_params(&self, mut params: CreateViewParams) -> Result<View, FlowyError> {
|
||||
let processor = self.get_data_processor(¶ms.data_type)?;
|
||||
let content = if params.data.is_empty() {
|
||||
let default_view_data = processor.default_view_data(¶ms.view_id);
|
||||
params.data = default_view_data.clone();
|
||||
default_view_data
|
||||
|
||||
if params.data.is_empty() {
|
||||
let user_id = self.user.user_id()?;
|
||||
let view_data = processor.create_default_view(&user_id, ¶ms.view_id).await?;
|
||||
params.data = view_data;
|
||||
} else {
|
||||
params.data.clone()
|
||||
let delta_data = Bytes::from(params.data.clone());
|
||||
let _ = self
|
||||
.create_view(¶ms.view_id, params.data_type.clone(), delta_data)
|
||||
.await?;
|
||||
};
|
||||
|
||||
let delta_data = Bytes::from(content);
|
||||
let _ = self
|
||||
.create_view(¶ms.view_id, params.data_type.clone(), delta_data)
|
||||
.await?;
|
||||
let view = self.create_view_on_server(params).await?;
|
||||
let _ = self.create_view_on_local(view.clone()).await?;
|
||||
Ok(view)
|
||||
@ -86,9 +83,8 @@ impl ViewController {
|
||||
return Err(FlowyError::internal().context("The content of the view should not be empty"));
|
||||
}
|
||||
let user_id = self.user.user_id()?;
|
||||
let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, view_id, delta_data).into();
|
||||
let processor = self.get_data_processor(&data_type)?;
|
||||
let _ = processor.create_container(view_id, repeated_revision).await?;
|
||||
let _ = processor.create_container(&user_id, view_id, delta_data).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest};
|
||||
use flowy_collaboration::{client_document::default::initial_quill_delta_string, entities::revision::RevisionState};
|
||||
|
||||
use flowy_folder::entities::workspace::CreateWorkspacePayload;
|
||||
use flowy_sync::disk::RevisionState;
|
||||
use flowy_test::{event_builder::*, FlowySDKTest};
|
||||
|
||||
#[tokio::test]
|
||||
@ -168,16 +169,6 @@ async fn view_update() {
|
||||
assert_eq!(test.view.name, new_name);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn open_document_view() {
|
||||
let mut test = FolderTest::new().await;
|
||||
assert_eq!(test.document_info, None);
|
||||
|
||||
test.run_scripts(vec![OpenDocument]).await;
|
||||
let document_info = test.document_info.unwrap();
|
||||
assert_eq!(document_info.text, initial_quill_delta_string());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
async fn view_delete() {
|
||||
|
@ -161,7 +161,8 @@ pub async fn delete_view(sdk: &FlowySDKTest, view_ids: Vec<String>) {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn open_document(sdk: &FlowySDKTest, view_id: &str) -> TextBlockInfo {
|
||||
#[allow(dead_code)]
|
||||
pub async fn set_latest_view(sdk: &FlowySDKTest, view_id: &str) -> TextBlockInfo {
|
||||
let view_id: ViewId = view_id.into();
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(SetLatestView)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::helper::*;
|
||||
use flowy_collaboration::entities::{revision::RevisionState, text_block_info::TextBlockInfo};
|
||||
|
||||
use flowy_folder::{errors::ErrorCode, services::folder_editor::ClientFolderEditor};
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::{App, RepeatedApp},
|
||||
@ -7,6 +7,7 @@ use flowy_folder_data_model::entities::{
|
||||
view::{RepeatedView, View, ViewDataType},
|
||||
workspace::Workspace,
|
||||
};
|
||||
use flowy_sync::disk::RevisionState;
|
||||
use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS;
|
||||
use flowy_test::FlowySDKTest;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
@ -42,9 +43,6 @@ pub enum FolderScript {
|
||||
ReadTrash,
|
||||
DeleteAllTrash,
|
||||
|
||||
// Document
|
||||
OpenDocument,
|
||||
|
||||
// Sync
|
||||
AssertCurrentRevId(i64),
|
||||
AssertNextSyncRevId(Option<i64>),
|
||||
@ -58,7 +56,6 @@ pub struct FolderTest {
|
||||
pub app: App,
|
||||
pub view: View,
|
||||
pub trash: Vec<Trash>,
|
||||
pub document_info: Option<TextBlockInfo>,
|
||||
// pub folder_editor:
|
||||
}
|
||||
|
||||
@ -68,7 +65,14 @@ impl FolderTest {
|
||||
let _ = sdk.init_user().await;
|
||||
let mut workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await;
|
||||
let mut app = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await;
|
||||
let view = create_view(&sdk, &app.id, "Folder View", "Folder test view", ViewDataType::Block).await;
|
||||
let view = create_view(
|
||||
&sdk,
|
||||
&app.id,
|
||||
"Folder View",
|
||||
"Folder test view",
|
||||
ViewDataType::TextBlock,
|
||||
)
|
||||
.await;
|
||||
app.belongings = RepeatedView {
|
||||
items: vec![view.clone()],
|
||||
};
|
||||
@ -83,7 +87,6 @@ impl FolderTest {
|
||||
app,
|
||||
view,
|
||||
trash: vec![],
|
||||
document_info: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +149,7 @@ impl FolderTest {
|
||||
}
|
||||
|
||||
FolderScript::CreateView { name, desc } => {
|
||||
let view = create_view(sdk, &self.app.id, &name, &desc, ViewDataType::Block).await;
|
||||
let view = create_view(sdk, &self.app.id, &name, &desc, ViewDataType::TextBlock).await;
|
||||
self.view = view;
|
||||
}
|
||||
FolderScript::AssertView(view) => {
|
||||
@ -179,10 +182,6 @@ impl FolderTest {
|
||||
delete_all_trash(sdk).await;
|
||||
self.trash = vec![];
|
||||
}
|
||||
FolderScript::OpenDocument => {
|
||||
let document_info = open_document(sdk, &self.view.id).await;
|
||||
self.document_info = Some(document_info);
|
||||
}
|
||||
FolderScript::AssertRevisionState { rev_id, state } => {
|
||||
let record = cache.get(rev_id).await.unwrap();
|
||||
assert_eq!(record.state, state);
|
||||
|
@ -46,7 +46,7 @@ pub(crate) async fn create_row_handler(
|
||||
) -> Result<(), FlowyError> {
|
||||
let id: GridId = data.into_inner();
|
||||
let editor = manager.get_grid_editor(id.as_ref())?;
|
||||
let _ = editor.create_empty_row().await?;
|
||||
let _ = editor.create_row().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ pub(crate) async fn update_cell_handler(
|
||||
data: Data<Cell>,
|
||||
manager: AppData<Arc<GridManager>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let cell: Cell = data.into_inner();
|
||||
let _cell: Cell = data.into_inner();
|
||||
// let editor = manager.get_grid_editor(id.as_ref())?;
|
||||
// let _ = editor.create_empty_row().await?;
|
||||
Ok(())
|
||||
|
@ -1,13 +1,10 @@
|
||||
use crate::services::grid_editor::ClientGridEditor;
|
||||
use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
|
||||
use crate::services::kv_persistence::GridKVPersistence;
|
||||
use dashmap::DashMap;
|
||||
|
||||
use flowy_collaboration::entities::revision::RepeatedRevision;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{Field, RowMeta};
|
||||
use flowy_sync::disk::{SQLiteGridBlockMetaRevisionPersistence, SQLiteGridRevisionPersistence};
|
||||
use flowy_sync::{RevisionManager, RevisionPersistence, RevisionWebSocket};
|
||||
|
||||
use flowy_sync::disk::SQLiteGridRevisionPersistence;
|
||||
use lib_sqlite::ConnectionPool;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
@ -47,6 +44,19 @@ impl GridManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub async fn create_grid_block_meta<T: AsRef<str>>(
|
||||
&self,
|
||||
block_id: T,
|
||||
revisions: RepeatedRevision,
|
||||
) -> FlowyResult<()> {
|
||||
let block_id = block_id.as_ref();
|
||||
let db_pool = self.grid_user.db_pool()?;
|
||||
let rev_manager = self.make_grid_block_meta_rev_manager(block_id, db_pool)?;
|
||||
let _ = rev_manager.reset_object(revisions).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(grid_id), err)]
|
||||
pub async fn open_grid<T: AsRef<str>>(&self, grid_id: T) -> FlowyResult<Arc<ClientGridEditor>> {
|
||||
let grid_id = grid_id.as_ref();
|
||||
@ -112,6 +122,18 @@ impl GridManager {
|
||||
Ok(rev_manager)
|
||||
}
|
||||
|
||||
fn make_grid_block_meta_rev_manager(
|
||||
&self,
|
||||
block_d: &str,
|
||||
pool: Arc<ConnectionPool>,
|
||||
) -> FlowyResult<RevisionManager> {
|
||||
let user_id = self.grid_user.user_id()?;
|
||||
let disk_cache = Arc::new(SQLiteGridBlockMetaRevisionPersistence::new(&user_id, pool));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, block_d, disk_cache));
|
||||
let rev_manager = RevisionManager::new(&user_id, block_d, rev_persistence);
|
||||
Ok(rev_manager)
|
||||
}
|
||||
|
||||
fn get_kv_persistence(&self) -> FlowyResult<Arc<GridKVPersistence>> {
|
||||
let read_guard = self.kv_persistence.read();
|
||||
if read_guard.is_some() {
|
||||
|
@ -1,77 +0,0 @@
|
||||
use crate::manager::GridManager;
|
||||
use flowy_collaboration::client_grid::make_grid_delta;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{CellMeta, Field, FieldType, Grid, GridMeta, RowMeta, RowOrder};
|
||||
use lib_infra::uuid;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct GridBuilder {
|
||||
grid_manager: Arc<GridManager>,
|
||||
grid_id: String,
|
||||
fields: Vec<Field>,
|
||||
rows: Vec<RowMeta>,
|
||||
}
|
||||
|
||||
impl GridBuilder {
|
||||
pub fn new(grid_id: &str, grid_manager: Arc<GridManager>) -> Self {
|
||||
Self {
|
||||
grid_manager,
|
||||
grid_id: grid_id.to_owned(),
|
||||
fields: vec![],
|
||||
rows: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_field(mut self, name: &str, desc: &str, field_type: FieldType) -> Self {
|
||||
let field = Field::new(&uuid(), name, desc, field_type);
|
||||
self.fields.push(field);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_empty_row(mut self) -> Self {
|
||||
let row = RowMeta::new(&uuid(), &self.grid_id, vec![]);
|
||||
self.rows.push(row);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_row(mut self, cells: Vec<CellMeta>) -> Self {
|
||||
let row = RowMeta::new(&uuid(), &self.grid_id, cells);
|
||||
self.rows.push(row);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> FlowyResult<String> {
|
||||
let grid_meta = GridMeta {
|
||||
grid_id: self.grid_id,
|
||||
fields: self.fields,
|
||||
blocks: vec![],
|
||||
};
|
||||
|
||||
// let _ = check_rows(&self.fields, &self.rows)?;
|
||||
let delta = make_grid_delta(&grid_meta);
|
||||
Ok(delta.to_delta_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn check_rows(fields: &[Field], rows: &[RowMeta]) -> FlowyResult<()> {
|
||||
let field_ids = fields.iter().map(|field| &field.id).collect::<Vec<&String>>();
|
||||
for row in rows {
|
||||
let cell_field_ids = row.cell_by_field_id.keys().into_iter().collect::<Vec<&String>>();
|
||||
if cell_field_ids != field_ids {
|
||||
let msg = format!("{:?} contains invalid cells", row);
|
||||
return Err(FlowyError::internal().context(msg));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn make_default_grid(grid_id: &str, grid_manager: Arc<GridManager>) -> String {
|
||||
GridBuilder::new(grid_id, grid_manager)
|
||||
.add_field("Name", "", FieldType::RichText)
|
||||
.add_field("Tags", "", FieldType::SingleSelect)
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
use crate::manager::GridUser;
|
||||
use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
|
||||
use crate::services::stringify::stringify_deserialize;
|
||||
|
||||
use crate::services::grid_meta_editor::ClientGridBlockMetaEditor;
|
||||
use bytes::Bytes;
|
||||
@ -10,14 +9,14 @@ 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::{
|
||||
Cell, CellMeta, Field, Grid, RepeatedField, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder, Row, RowMeta,
|
||||
Field, Grid, GridBlock, RepeatedField, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder,
|
||||
};
|
||||
use flowy_sync::disk::SQLiteGridBlockMetaRevisionPersistence;
|
||||
use flowy_sync::{
|
||||
RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
|
||||
};
|
||||
use flowy_sync::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::{Delta, PlainTextAttributes};
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use std::collections::HashMap;
|
||||
use lib_ot::core::PlainTextAttributes;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
@ -40,10 +39,11 @@ impl ClientGridEditor {
|
||||
let token = user.token()?;
|
||||
let cloud = Arc::new(GridRevisionCloudService { token });
|
||||
let grid_pad = rev_manager.load::<GridPadBuilder>(cloud).await?;
|
||||
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let grid_meta_pad = Arc::new(RwLock::new(grid_pad));
|
||||
let block_meta_manager = Arc::new(GridBlockMetaEditorManager::new());
|
||||
|
||||
let block_meta_manager =
|
||||
Arc::new(GridBlockMetaEditorManager::new(&user, grid_meta_pad.read().await.get_blocks()).await?);
|
||||
|
||||
Ok(Arc::new(Self {
|
||||
grid_id: grid_id.to_owned(),
|
||||
@ -65,25 +65,15 @@ impl ClientGridEditor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn create_empty_row(&self) -> FlowyResult<()> {
|
||||
// let _ = self.modify(|grid| {
|
||||
//
|
||||
//
|
||||
// grid.blocks
|
||||
//
|
||||
// }).await?;
|
||||
pub async fn create_row(&self) -> FlowyResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn create_row(&self, row: RowMeta) -> FlowyResult<()> {
|
||||
pub async fn get_rows(&self, _row_orders: RepeatedRowOrder) -> FlowyResult<RepeatedRow> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> FlowyResult<RepeatedRow> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn delete_rows(&self, ids: Vec<String>) -> FlowyResult<()> {
|
||||
pub async fn delete_rows(&self, _ids: Vec<String>) -> FlowyResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -188,13 +178,17 @@ struct GridBlockMetaEditorManager {
|
||||
}
|
||||
|
||||
impl GridBlockMetaEditorManager {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
editor_map: DashMap::new(),
|
||||
}
|
||||
async fn new(user: &Arc<dyn GridUser>, blocks: Vec<GridBlock>) -> FlowyResult<Self> {
|
||||
let editor_map = make_block_meta_editor_map(user, blocks).await?;
|
||||
let manager = Self { editor_map };
|
||||
Ok(manager)
|
||||
}
|
||||
|
||||
pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> FlowyResult<RepeatedRow> {
|
||||
async fn get_editor(&self, _block_id: &str) -> Arc<ClientGridBlockMetaEditor> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn get_rows(&self, _row_orders: RepeatedRowOrder) -> FlowyResult<RepeatedRow> {
|
||||
// let ids = row_orders
|
||||
// .items
|
||||
// .into_iter()
|
||||
@ -245,3 +239,23 @@ impl GridBlockMetaEditorManager {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
async fn make_block_meta_editor_map(
|
||||
user: &Arc<dyn GridUser>,
|
||||
blocks: Vec<GridBlock>,
|
||||
) -> FlowyResult<DashMap<String, Arc<ClientGridBlockMetaEditor>>> {
|
||||
let token = user.token()?;
|
||||
let user_id = user.user_id()?;
|
||||
let pool = user.db_pool()?;
|
||||
|
||||
let editor_map = DashMap::new();
|
||||
for block in blocks {
|
||||
let disk_cache = Arc::new(SQLiteGridBlockMetaRevisionPersistence::new(&user_id, pool.clone()));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, &block.id, disk_cache));
|
||||
let rev_manager = RevisionManager::new(&user_id, &block.id, rev_persistence);
|
||||
let editor = ClientGridBlockMetaEditor::new(&user_id, &token, &block.id, rev_manager).await?;
|
||||
editor_map.insert(block.id, Arc::new(editor));
|
||||
}
|
||||
|
||||
Ok(editor_map)
|
||||
}
|
||||
|
@ -3,17 +3,16 @@ 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::RowMeta;
|
||||
use flowy_grid_data_model::entities::{RowMeta, RowMetaChangeset};
|
||||
use flowy_sync::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::PlainTextAttributes;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
pub struct ClientGridBlockMetaEditor {
|
||||
user_id: String,
|
||||
block_id: String,
|
||||
pub block_id: String,
|
||||
meta_pad: Arc<RwLock<GridBlockMetaPad>>,
|
||||
rev_manager: Arc<RevisionManager>,
|
||||
}
|
||||
@ -22,7 +21,7 @@ impl ClientGridBlockMetaEditor {
|
||||
pub async fn new(
|
||||
user_id: &str,
|
||||
token: &str,
|
||||
block_id: String,
|
||||
block_id: &str,
|
||||
mut rev_manager: RevisionManager,
|
||||
) -> FlowyResult<Self> {
|
||||
let cloud = Arc::new(GridBlockMetaRevisionCloudService {
|
||||
@ -32,6 +31,7 @@ impl ClientGridBlockMetaEditor {
|
||||
let meta_pad = Arc::new(RwLock::new(block_meta_pad));
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let user_id = user_id.to_owned();
|
||||
let block_id = block_id.to_owned();
|
||||
Ok(Self {
|
||||
user_id,
|
||||
block_id,
|
||||
@ -40,25 +40,27 @@ impl ClientGridBlockMetaEditor {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn create_empty_row(&self) -> FlowyResult<()> {
|
||||
let row = RowMeta::new(&uuid(), &self.block_id, vec![]);
|
||||
self.create_row(row).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_row(&self, row: RowMeta) -> FlowyResult<()> {
|
||||
// let _ = self.modify(|grid| Ok(grid.create_row(row)?)).await?;
|
||||
// self.cell_map.insert(row.id.clone(), row.clone());
|
||||
// let _ = self.kv_persistence.set(row)?;
|
||||
async fn create_row(&self) -> FlowyResult<()> {
|
||||
let row = RowMeta::new(&self.block_id, vec![]);
|
||||
let _ = self.modify(|pad| Ok(pad.add_row(row)?)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn delete_rows(&self, ids: Vec<String>) -> FlowyResult<()> {
|
||||
// let _ = self.modify(|grid| Ok(grid.delete_rows(&ids)?)).await?;
|
||||
// let _ = self.kv.batch_delete(ids)?;
|
||||
let _ = self.modify(|pad| Ok(pad.delete_rows(&ids)?)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {
|
||||
let _ = self.modify(|pad| Ok(pad.update_row(changeset)?)).await?;
|
||||
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)
|
||||
}
|
||||
|
||||
async fn modify<F>(&self, f: F) -> FlowyResult<()>
|
||||
where
|
||||
F: for<'a> FnOnce(&'a mut GridBlockMetaPad) -> FlowyResult<Option<GridBlockMetaChange>>,
|
||||
|
@ -1,7 +1,6 @@
|
||||
mod util;
|
||||
|
||||
pub mod cell_data;
|
||||
pub mod grid_builder;
|
||||
pub mod grid_editor;
|
||||
pub mod grid_meta_editor;
|
||||
pub mod kv_persistence;
|
||||
|
0
frontend/rust-lib/flowy-grid/tests/grid_test.rs
Normal file
0
frontend/rust-lib/flowy-grid/tests/grid_test.rs
Normal file
@ -29,25 +29,25 @@ pub trait RevisionCloudStorage: Send + Sync {
|
||||
) -> BoxResultFuture<(), CollaborateError>;
|
||||
}
|
||||
|
||||
pub(crate) struct LocalDocumentCloudPersistence {
|
||||
pub(crate) struct LocalTextBlockCloudPersistence {
|
||||
storage: Arc<dyn RevisionCloudStorage>,
|
||||
}
|
||||
|
||||
impl Debug for LocalDocumentCloudPersistence {
|
||||
impl Debug for LocalTextBlockCloudPersistence {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("LocalRevisionCloudPersistence")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::default::Default for LocalDocumentCloudPersistence {
|
||||
impl std::default::Default for LocalTextBlockCloudPersistence {
|
||||
fn default() -> Self {
|
||||
LocalDocumentCloudPersistence {
|
||||
LocalTextBlockCloudPersistence {
|
||||
storage: Arc::new(MemoryDocumentCloudStorage::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FolderCloudPersistence for LocalDocumentCloudPersistence {
|
||||
impl FolderCloudPersistence for LocalTextBlockCloudPersistence {
|
||||
fn read_folder(&self, _user_id: &str, folder_id: &str) -> BoxResultFuture<FolderInfo, CollaborateError> {
|
||||
let storage = self.storage.clone();
|
||||
let folder_id = folder_id.to_owned();
|
||||
@ -110,8 +110,8 @@ impl FolderCloudPersistence for LocalDocumentCloudPersistence {
|
||||
}
|
||||
}
|
||||
|
||||
impl DocumentCloudPersistence for LocalDocumentCloudPersistence {
|
||||
fn read_document(&self, doc_id: &str) -> BoxResultFuture<TextBlockInfo, CollaborateError> {
|
||||
impl TextBlockCloudPersistence for LocalTextBlockCloudPersistence {
|
||||
fn read_text_block(&self, doc_id: &str) -> BoxResultFuture<TextBlockInfo, CollaborateError> {
|
||||
let storage = self.storage.clone();
|
||||
let doc_id = doc_id.to_owned();
|
||||
Box::pin(async move {
|
||||
@ -123,7 +123,7 @@ impl DocumentCloudPersistence for LocalDocumentCloudPersistence {
|
||||
})
|
||||
}
|
||||
|
||||
fn create_document(
|
||||
fn create_text_block(
|
||||
&self,
|
||||
doc_id: &str,
|
||||
repeated_revision: RepeatedRevisionPB,
|
||||
@ -136,7 +136,7 @@ impl DocumentCloudPersistence for LocalDocumentCloudPersistence {
|
||||
})
|
||||
}
|
||||
|
||||
fn read_document_revisions(
|
||||
fn read_text_block_revisions(
|
||||
&self,
|
||||
doc_id: &str,
|
||||
rev_ids: Option<Vec<i64>>,
|
||||
@ -150,7 +150,10 @@ impl DocumentCloudPersistence for LocalDocumentCloudPersistence {
|
||||
})
|
||||
}
|
||||
|
||||
fn save_document_revisions(&self, repeated_revision: RepeatedRevisionPB) -> BoxResultFuture<(), CollaborateError> {
|
||||
fn save_text_block_revisions(
|
||||
&self,
|
||||
repeated_revision: RepeatedRevisionPB,
|
||||
) -> BoxResultFuture<(), CollaborateError> {
|
||||
let storage = self.storage.clone();
|
||||
Box::pin(async move {
|
||||
let _ = storage.set_revisions(repeated_revision).await?;
|
||||
@ -158,7 +161,7 @@ impl DocumentCloudPersistence for LocalDocumentCloudPersistence {
|
||||
})
|
||||
}
|
||||
|
||||
fn reset_document(&self, doc_id: &str, revisions: RepeatedRevisionPB) -> BoxResultFuture<(), CollaborateError> {
|
||||
fn reset_text_block(&self, doc_id: &str, revisions: RepeatedRevisionPB) -> BoxResultFuture<(), CollaborateError> {
|
||||
let storage = self.storage.clone();
|
||||
let doc_id = doc_id.to_owned();
|
||||
Box::pin(async move {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::local_server::persistence::LocalDocumentCloudPersistence;
|
||||
use crate::local_server::persistence::LocalTextBlockCloudPersistence;
|
||||
use async_stream::stream;
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::{
|
||||
@ -38,7 +38,7 @@ impl LocalServer {
|
||||
client_ws_sender: mpsc::UnboundedSender<WebSocketRawMessage>,
|
||||
client_ws_receiver: broadcast::Sender<WebSocketRawMessage>,
|
||||
) -> Self {
|
||||
let persistence = Arc::new(LocalDocumentCloudPersistence::default());
|
||||
let persistence = Arc::new(LocalTextBlockCloudPersistence::default());
|
||||
let doc_manager = Arc::new(ServerDocumentManager::new(persistence.clone()));
|
||||
let folder_manager = Arc::new(ServerFolderManager::new(persistence));
|
||||
let stop_tx = RwLock::new(None);
|
||||
|
@ -1,7 +1,8 @@
|
||||
use bytes::Bytes;
|
||||
use flowy_block::TextBlockManager;
|
||||
use flowy_collaboration::client_document::default::initial_quill_delta_string;
|
||||
use flowy_collaboration::entities::revision::RepeatedRevision;
|
||||
use flowy_collaboration::client_grid::make_default_grid;
|
||||
use flowy_collaboration::entities::revision::{RepeatedRevision, Revision};
|
||||
use flowy_collaboration::entities::ws_data::ClientRevisionWSData;
|
||||
use flowy_database::ConnectionPool;
|
||||
use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||
@ -12,7 +13,6 @@ use flowy_folder::{
|
||||
manager::FolderManager,
|
||||
};
|
||||
use flowy_grid::manager::GridManager;
|
||||
use flowy_grid::services::grid_builder::make_default_grid;
|
||||
use flowy_net::ClientServerConfiguration;
|
||||
use flowy_net::{
|
||||
http_server::folder::FolderHttpCloudService, local_server::LocalServer, ws::connection::FlowyWebSocketConnect,
|
||||
@ -140,9 +140,10 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
|
||||
FutureResult::new(async move { manager.init() })
|
||||
}
|
||||
|
||||
fn create_container(&self, view_id: &str, repeated_revision: RepeatedRevision) -> FutureResult<(), FlowyError> {
|
||||
let manager = self.0.clone();
|
||||
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError> {
|
||||
let repeated_revision: RepeatedRevision = Revision::initial_revision(user_id, view_id, delta_data).into();
|
||||
let view_id = view_id.to_string();
|
||||
let manager = self.0.clone();
|
||||
FutureResult::new(async move {
|
||||
let _ = manager.create_block(view_id, repeated_revision).await?;
|
||||
Ok(())
|
||||
@ -177,12 +178,21 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
|
||||
})
|
||||
}
|
||||
|
||||
fn default_view_data(&self, _view_id: &str) -> String {
|
||||
initial_quill_delta_string()
|
||||
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<String, FlowyError> {
|
||||
let user_id = user_id.to_string();
|
||||
let view_id = view_id.to_string();
|
||||
let manager = self.0.clone();
|
||||
FutureResult::new(async move {
|
||||
let view_data = initial_quill_delta_string();
|
||||
let delta_data = Bytes::from(view_data.clone());
|
||||
let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, &view_id, delta_data).into();
|
||||
let _ = manager.create_block(view_id, repeated_revision).await?;
|
||||
Ok(view_data)
|
||||
})
|
||||
}
|
||||
|
||||
fn data_type(&self) -> ViewDataType {
|
||||
ViewDataType::Block
|
||||
ViewDataType::TextBlock
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,9 +202,10 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
||||
FutureResult::new(async { Ok(()) })
|
||||
}
|
||||
|
||||
fn create_container(&self, view_id: &str, repeated_revision: RepeatedRevision) -> FutureResult<(), FlowyError> {
|
||||
let grid_manager = self.0.clone();
|
||||
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError> {
|
||||
let repeated_revision: RepeatedRevision = Revision::initial_revision(user_id, view_id, delta_data).into();
|
||||
let view_id = view_id.to_string();
|
||||
let grid_manager = self.0.clone();
|
||||
FutureResult::new(async move {
|
||||
let _ = grid_manager.create_grid(view_id, repeated_revision).await?;
|
||||
Ok(())
|
||||
@ -229,8 +240,27 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
||||
})
|
||||
}
|
||||
|
||||
fn default_view_data(&self, view_id: &str) -> String {
|
||||
make_default_grid(view_id, self.0.clone())
|
||||
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<String, FlowyError> {
|
||||
let info = make_default_grid(view_id);
|
||||
let user_id = user_id.to_string();
|
||||
let view_id = view_id.to_string();
|
||||
let grid_manager = self.0.clone();
|
||||
|
||||
FutureResult::new(async move {
|
||||
let grid_delta_data = Bytes::from(info.grid_delta.to_delta_str());
|
||||
let repeated_revision: RepeatedRevision =
|
||||
Revision::initial_revision(&user_id, &view_id, grid_delta_data).into();
|
||||
let _ = grid_manager.create_grid(&view_id, repeated_revision).await?;
|
||||
|
||||
let block_meta_delta_data = Bytes::from(info.grid_block_meta_delta.to_delta_str());
|
||||
let repeated_revision: RepeatedRevision =
|
||||
Revision::initial_revision(&user_id, &info.block_id, block_meta_delta_data).into();
|
||||
let _ = grid_manager
|
||||
.create_grid_block_meta(&info.block_id, repeated_revision)
|
||||
.await?;
|
||||
|
||||
Ok(info.grid_delta.to_delta_str())
|
||||
})
|
||||
}
|
||||
|
||||
fn data_type(&self) -> ViewDataType {
|
||||
|
@ -1,10 +1,10 @@
|
||||
use crate::cache::disk::RevisionDiskCache;
|
||||
use crate::disk::{RevisionChangeset, RevisionRecord, RevisionState};
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
|
||||
use bytes::Bytes;
|
||||
use diesel::{sql_types::Integer, update, SqliteConnection};
|
||||
use flowy_collaboration::{
|
||||
entities::revision::{RevId, RevType, Revision, RevisionRange},
|
||||
entities::revision::{Revision, RevisionRange},
|
||||
util::md5,
|
||||
};
|
||||
use flowy_database::{
|
||||
|
@ -1,10 +1,10 @@
|
||||
use crate::cache::disk::RevisionDiskCache;
|
||||
use crate::disk::{RevisionChangeset, RevisionRecord, RevisionState};
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
|
||||
use bytes::Bytes;
|
||||
use diesel::{sql_types::Integer, update, SqliteConnection};
|
||||
use flowy_collaboration::{
|
||||
entities::revision::{RevId, RevType, Revision, RevisionRange},
|
||||
entities::revision::{Revision, RevisionRange},
|
||||
util::md5,
|
||||
};
|
||||
use flowy_database::{
|
||||
|
@ -8,8 +8,6 @@ pub use grid_meta_rev_impl::*;
|
||||
pub use grid_rev_impl::*;
|
||||
pub use text_rev_impl::*;
|
||||
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
use diesel::SqliteConnection;
|
||||
use flowy_collaboration::entities::revision::{RevId, Revision, RevisionRange};
|
||||
use flowy_error::FlowyResult;
|
||||
use std::fmt::Debug;
|
||||
|
@ -1,10 +1,10 @@
|
||||
use crate::cache::disk::RevisionDiskCache;
|
||||
use crate::disk::{RevisionChangeset, RevisionRecord, RevisionState};
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
|
||||
use bytes::Bytes;
|
||||
use diesel::{sql_types::Integer, update, SqliteConnection};
|
||||
use flowy_collaboration::{
|
||||
entities::revision::{RevId, RevType, Revision, RevisionRange},
|
||||
entities::revision::{RevType, Revision, RevisionRange},
|
||||
util::md5,
|
||||
};
|
||||
use flowy_database::{
|
||||
|
@ -7,7 +7,6 @@ use flowy_collaboration::{
|
||||
};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_ot::core::{Attributes, Delta};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait RevisionCloudService: Send + Sync {
|
||||
|
@ -88,7 +88,7 @@ async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View {
|
||||
name: "View A".to_string(),
|
||||
desc: "".to_string(),
|
||||
thumbnail: Some("http://1.png".to_string()),
|
||||
data_type: ViewDataType::Block,
|
||||
data_type: ViewDataType::TextBlock,
|
||||
ext_data: "".to_string(),
|
||||
plugin_type: 0,
|
||||
};
|
||||
|
@ -1,10 +1,11 @@
|
||||
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::{GridBlockMeta, RowMeta, RowMetaChangeset, RowOrder};
|
||||
use flowy_grid_data_model::entities::{GridBlockMeta, RowMeta, RowMetaChangeset};
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type GridBlockMetaDelta = PlainTextDelta;
|
||||
@ -49,6 +50,25 @@ impl GridBlockMetaPad {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_rows(&self, row_ids: Vec<String>) -> CollaborateResult<Vec<RowMeta>> {
|
||||
let row_map = self
|
||||
.rows
|
||||
.iter()
|
||||
.map(|row| (&row.id, row.clone()))
|
||||
.collect::<HashMap<&String, Arc<RowMeta>>>();
|
||||
|
||||
Ok(row_ids
|
||||
.iter()
|
||||
.flat_map(|row_id| match row_map.get(row_id) {
|
||||
None => {
|
||||
tracing::error!("Can't find the row with id: {}", row_id);
|
||||
None
|
||||
}
|
||||
Some(row) => Some((**row).clone()),
|
||||
})
|
||||
.collect::<Vec<RowMeta>>())
|
||||
}
|
||||
|
||||
pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult<Option<GridBlockMetaChange>> {
|
||||
let row_id = changeset.row_id.clone();
|
||||
self.modify_row(&row_id, |row| {
|
||||
@ -123,12 +143,6 @@ impl GridBlockMetaPad {
|
||||
}
|
||||
}
|
||||
|
||||
fn json_from_grid(block_meta: &Arc<GridBlockMeta>) -> CollaborateResult<String> {
|
||||
let json = serde_json::to_string(block_meta)
|
||||
.map_err(|err| internal_error(format!("Serialize grid to json str failed. {:?}", err)))?;
|
||||
Ok(json)
|
||||
}
|
||||
|
||||
pub struct GridBlockMetaChange {
|
||||
pub delta: GridBlockMetaDelta,
|
||||
/// md5: the md5 of the grid after applying the change.
|
||||
@ -165,9 +179,8 @@ impl std::default::Default for GridBlockMetaPad {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::client_grid::{GridBlockMetaDelta, GridMetaPad};
|
||||
use crate::client_grid::{GridBlockMetaDelta, GridBlockMetaPad};
|
||||
use flowy_grid_data_model::entities::{RowMeta, RowMetaChangeset};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn block_meta_add_row() {
|
||||
@ -227,7 +240,7 @@ mod tests {
|
||||
cell_by_field_id: Default::default(),
|
||||
};
|
||||
|
||||
let _ = pad.add_row(row.clone()).unwrap().unwrap();
|
||||
let _ = pad.add_row(row).unwrap().unwrap();
|
||||
let change = pad.update_row(changeset).unwrap().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@ -241,8 +254,8 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
fn test_pad() -> GridMetaPad {
|
||||
fn test_pad() -> GridBlockMetaPad {
|
||||
let delta = GridBlockMetaDelta::from_delta_str(r#"[{"insert":"{\"block_id\":\"1\",\"rows\":[]}"}]"#).unwrap();
|
||||
GridMetaPad::from_delta(delta).unwrap()
|
||||
GridBlockMetaPad::from_delta(delta).unwrap()
|
||||
}
|
||||
}
|
||||
|
114
shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs
Normal file
114
shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs
Normal file
@ -0,0 +1,114 @@
|
||||
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};
|
||||
|
||||
pub struct GridBuilder {
|
||||
grid_id: String,
|
||||
fields: Vec<Field>,
|
||||
grid_block: GridBlock,
|
||||
grid_block_meta: GridBlockMeta,
|
||||
}
|
||||
|
||||
impl GridBuilder {
|
||||
pub fn new(grid_id: &str) -> Self {
|
||||
let grid_block = GridBlock::new();
|
||||
let grid_block_meta = GridBlockMeta {
|
||||
block_id: grid_block.id.clone(),
|
||||
rows: vec![],
|
||||
};
|
||||
|
||||
Self {
|
||||
grid_id: grid_id.to_owned(),
|
||||
fields: vec![],
|
||||
grid_block,
|
||||
grid_block_meta,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_field(mut self, name: &str, desc: &str, field_type: FieldType) -> Self {
|
||||
let field = Field::new(name, desc, field_type);
|
||||
self.fields.push(field);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_empty_row(mut self) -> Self {
|
||||
let row = RowMeta::new(&self.grid_block.id, vec![]);
|
||||
self.grid_block_meta.rows.push(row);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> CollaborateResult<BuildGridInfo> {
|
||||
let block_id = self.grid_block.id.clone();
|
||||
let grid_meta = GridMeta {
|
||||
grid_id: self.grid_id,
|
||||
fields: self.fields,
|
||||
blocks: vec![self.grid_block],
|
||||
};
|
||||
// let _ = check_rows(&self.fields, &self.rows)?;
|
||||
let grid_delta = make_grid_delta(&grid_meta);
|
||||
let grid_block_meta_delta = make_block_meta_delta(&self.grid_block_meta);
|
||||
Ok(BuildGridInfo {
|
||||
grid_delta,
|
||||
block_id,
|
||||
grid_block_meta_delta,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BuildGridInfo {
|
||||
pub grid_delta: GridMetaDelta,
|
||||
pub block_id: String,
|
||||
pub grid_block_meta_delta: GridBlockMetaDelta,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn check_rows(fields: &[Field], rows: &[RowMeta]) -> CollaborateResult<()> {
|
||||
let field_ids = fields.iter().map(|field| &field.id).collect::<Vec<&String>>();
|
||||
for row in rows {
|
||||
let cell_field_ids = row.cell_by_field_id.keys().into_iter().collect::<Vec<&String>>();
|
||||
if cell_field_ids != field_ids {
|
||||
let msg = format!("{:?} contains invalid cells", row);
|
||||
return Err(CollaborateError::internal().context(msg));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn make_default_grid(grid_id: &str) -> BuildGridInfo {
|
||||
GridBuilder::new(grid_id)
|
||||
.add_field("Name", "", FieldType::RichText)
|
||||
.add_field("Tags", "", FieldType::SingleSelect)
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::client_grid::GridBuilder;
|
||||
use flowy_grid_data_model::entities::{FieldType, GridBlockMeta, GridMeta};
|
||||
|
||||
#[test]
|
||||
fn create_default_grid_test() {
|
||||
let info = GridBuilder::new("1")
|
||||
.add_field("Name", "", FieldType::RichText)
|
||||
.add_field("Tags", "", FieldType::SingleSelect)
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let grid_meta: GridMeta = serde_json::from_str(&info.grid_delta.to_str().unwrap()).unwrap();
|
||||
assert_eq!(grid_meta.fields.len(), 2);
|
||||
assert_eq!(grid_meta.blocks.len(), 1);
|
||||
|
||||
let grid_block_meta: GridBlockMeta =
|
||||
serde_json::from_str(&info.grid_block_meta_delta.to_str().unwrap()).unwrap();
|
||||
assert_eq!(grid_block_meta.rows.len(), 3);
|
||||
|
||||
assert_eq!(grid_meta.blocks[0].id, grid_block_meta.block_id);
|
||||
}
|
||||
}
|
@ -2,24 +2,23 @@ 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, FieldOrder, Grid, GridBlock, GridBlockChangeset, GridMeta, RepeatedField,
|
||||
RepeatedFieldOrder, RowMeta, RowOrder,
|
||||
Field, FieldChangeset, GridBlock, GridBlockChangeset, GridMeta, RepeatedField, RepeatedFieldOrder,
|
||||
};
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type GridDelta = PlainTextDelta;
|
||||
pub type GridMetaDelta = PlainTextDelta;
|
||||
pub type GridDeltaBuilder = PlainTextDeltaBuilder;
|
||||
|
||||
pub struct GridMetaPad {
|
||||
pub(crate) grid_meta: Arc<GridMeta>,
|
||||
pub(crate) delta: GridDelta,
|
||||
pub(crate) delta: GridMetaDelta,
|
||||
}
|
||||
|
||||
impl GridMetaPad {
|
||||
pub fn from_delta(delta: GridDelta) -> CollaborateResult<Self> {
|
||||
pub fn from_delta(delta: GridMetaDelta) -> CollaborateResult<Self> {
|
||||
let s = delta.to_str()?;
|
||||
let grid: GridMeta = serde_json::from_str(&s)
|
||||
.map_err(|e| CollaborateError::internal().context(format!("Deserialize delta to grid failed: {}", e)))?;
|
||||
@ -31,7 +30,7 @@ impl GridMetaPad {
|
||||
}
|
||||
|
||||
pub fn from_revisions(_grid_id: &str, revisions: Vec<Revision>) -> CollaborateResult<Self> {
|
||||
let grid_delta: GridDelta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
|
||||
let grid_delta: GridMetaDelta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
|
||||
Self::from_delta(grid_delta)
|
||||
}
|
||||
|
||||
@ -64,7 +63,7 @@ impl GridMetaPad {
|
||||
.iter()
|
||||
.flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
|
||||
None => {
|
||||
tracing::error!("Can't find the field with {}", field_order.field_id);
|
||||
tracing::error!("Can't find the field with id: {}", field_order.field_id);
|
||||
None
|
||||
}
|
||||
Some(field) => Some((*field).clone()),
|
||||
@ -123,6 +122,10 @@ impl GridMetaPad {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_blocks(&self) -> Vec<GridBlock> {
|
||||
self.grid_meta.blocks.clone()
|
||||
}
|
||||
|
||||
pub fn update_block(&mut self, change: GridBlockChangeset) -> CollaborateResult<Option<GridChange>> {
|
||||
let block_id = change.block_id.clone();
|
||||
self.modify_block(&block_id, |block| {
|
||||
@ -204,12 +207,12 @@ fn json_from_grid(grid: &Arc<GridMeta>) -> CollaborateResult<String> {
|
||||
}
|
||||
|
||||
pub struct GridChange {
|
||||
pub delta: GridDelta,
|
||||
pub delta: GridMetaDelta,
|
||||
/// md5: the md5 of the grid after applying the change.
|
||||
pub md5: String,
|
||||
}
|
||||
|
||||
pub fn make_grid_delta(grid_meta: &GridMeta) -> GridDelta {
|
||||
pub fn make_grid_delta(grid_meta: &GridMeta) -> GridMetaDelta {
|
||||
let json = serde_json::to_string(&grid_meta).unwrap();
|
||||
PlainTextDeltaBuilder::new().insert(&json).build()
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
mod block_pad;
|
||||
mod grid_builder;
|
||||
mod grid_pad;
|
||||
|
||||
pub use block_pad::*;
|
||||
pub use grid_builder::*;
|
||||
pub use grid_pad::*;
|
||||
|
@ -17,41 +17,42 @@ use tokio::{
|
||||
task::spawn_blocking,
|
||||
};
|
||||
|
||||
pub trait DocumentCloudPersistence: Send + Sync + Debug {
|
||||
fn read_document(&self, doc_id: &str) -> BoxResultFuture<TextBlockInfo, CollaborateError>;
|
||||
pub trait TextBlockCloudPersistence: Send + Sync + Debug {
|
||||
fn read_text_block(&self, doc_id: &str) -> BoxResultFuture<TextBlockInfo, CollaborateError>;
|
||||
|
||||
fn create_document(
|
||||
fn create_text_block(
|
||||
&self,
|
||||
doc_id: &str,
|
||||
repeated_revision: RepeatedRevisionPB,
|
||||
) -> BoxResultFuture<Option<TextBlockInfo>, CollaborateError>;
|
||||
|
||||
fn read_document_revisions(
|
||||
fn read_text_block_revisions(
|
||||
&self,
|
||||
doc_id: &str,
|
||||
rev_ids: Option<Vec<i64>>,
|
||||
) -> BoxResultFuture<Vec<RevisionPB>, CollaborateError>;
|
||||
|
||||
fn save_document_revisions(&self, repeated_revision: RepeatedRevisionPB) -> BoxResultFuture<(), CollaborateError>;
|
||||
fn save_text_block_revisions(&self, repeated_revision: RepeatedRevisionPB)
|
||||
-> BoxResultFuture<(), CollaborateError>;
|
||||
|
||||
fn reset_document(
|
||||
fn reset_text_block(
|
||||
&self,
|
||||
doc_id: &str,
|
||||
repeated_revision: RepeatedRevisionPB,
|
||||
) -> BoxResultFuture<(), CollaborateError>;
|
||||
}
|
||||
|
||||
impl RevisionSyncPersistence for Arc<dyn DocumentCloudPersistence> {
|
||||
impl RevisionSyncPersistence for Arc<dyn TextBlockCloudPersistence> {
|
||||
fn read_revisions(
|
||||
&self,
|
||||
object_id: &str,
|
||||
rev_ids: Option<Vec<i64>>,
|
||||
) -> BoxResultFuture<Vec<RevisionPB>, CollaborateError> {
|
||||
(**self).read_document_revisions(object_id, rev_ids)
|
||||
(**self).read_text_block_revisions(object_id, rev_ids)
|
||||
}
|
||||
|
||||
fn save_revisions(&self, repeated_revision: RepeatedRevisionPB) -> BoxResultFuture<(), CollaborateError> {
|
||||
(**self).save_document_revisions(repeated_revision)
|
||||
(**self).save_text_block_revisions(repeated_revision)
|
||||
}
|
||||
|
||||
fn reset_object(
|
||||
@ -59,17 +60,17 @@ impl RevisionSyncPersistence for Arc<dyn DocumentCloudPersistence> {
|
||||
object_id: &str,
|
||||
repeated_revision: RepeatedRevisionPB,
|
||||
) -> BoxResultFuture<(), CollaborateError> {
|
||||
(**self).reset_document(object_id, repeated_revision)
|
||||
(**self).reset_text_block(object_id, repeated_revision)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ServerDocumentManager {
|
||||
document_handlers: Arc<RwLock<HashMap<String, Arc<OpenDocumentHandler>>>>,
|
||||
persistence: Arc<dyn DocumentCloudPersistence>,
|
||||
persistence: Arc<dyn TextBlockCloudPersistence>,
|
||||
}
|
||||
|
||||
impl ServerDocumentManager {
|
||||
pub fn new(persistence: Arc<dyn DocumentCloudPersistence>) -> Self {
|
||||
pub fn new(persistence: Arc<dyn TextBlockCloudPersistence>) -> Self {
|
||||
Self {
|
||||
document_handlers: Arc::new(RwLock::new(HashMap::new())),
|
||||
persistence,
|
||||
@ -151,7 +152,7 @@ impl ServerDocumentManager {
|
||||
}
|
||||
|
||||
let mut write_guard = self.document_handlers.write().await;
|
||||
match self.persistence.read_document(doc_id).await {
|
||||
match self.persistence.read_text_block(doc_id).await {
|
||||
Ok(doc) => {
|
||||
let handler = self.create_document_handler(doc).await.map_err(internal_error).unwrap();
|
||||
write_guard.insert(doc_id.to_owned(), handler.clone());
|
||||
@ -168,7 +169,7 @@ impl ServerDocumentManager {
|
||||
doc_id: &str,
|
||||
repeated_revision: RepeatedRevisionPB,
|
||||
) -> Result<Arc<OpenDocumentHandler>, CollaborateError> {
|
||||
match self.persistence.create_document(doc_id, repeated_revision).await? {
|
||||
match self.persistence.create_text_block(doc_id, repeated_revision).await? {
|
||||
None => Err(CollaborateError::internal().context("Create document info from revisions failed")),
|
||||
Some(doc) => {
|
||||
let handler = self.create_document_handler(doc).await?;
|
||||
@ -205,7 +206,7 @@ struct OpenDocumentHandler {
|
||||
}
|
||||
|
||||
impl OpenDocumentHandler {
|
||||
fn new(doc: TextBlockInfo, persistence: Arc<dyn DocumentCloudPersistence>) -> Result<Self, CollaborateError> {
|
||||
fn new(doc: TextBlockInfo, persistence: Arc<dyn TextBlockCloudPersistence>) -> Result<Self, CollaborateError> {
|
||||
let doc_id = doc.block_id.clone();
|
||||
let (sender, receiver) = mpsc::channel(1000);
|
||||
let users = DashMap::new();
|
||||
|
@ -83,24 +83,24 @@ impl std::convert::From<View> for Trash {
|
||||
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone, Serialize_repr, Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum ViewDataType {
|
||||
Block = 0,
|
||||
TextBlock = 0,
|
||||
Grid = 1,
|
||||
}
|
||||
|
||||
impl std::default::Default for ViewDataType {
|
||||
fn default() -> Self {
|
||||
ViewDataType::Block
|
||||
ViewDataType::TextBlock
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<i32> for ViewDataType {
|
||||
fn from(val: i32) -> Self {
|
||||
match val {
|
||||
0 => ViewDataType::Block,
|
||||
0 => ViewDataType::TextBlock,
|
||||
1 => ViewDataType::Grid,
|
||||
_ => {
|
||||
log::error!("Invalid view type: {}", val);
|
||||
ViewDataType::Block
|
||||
ViewDataType::TextBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ impl View {
|
||||
self.data_type
|
||||
}
|
||||
pub fn clear_data_type(&mut self) {
|
||||
self.data_type = ViewDataType::Block;
|
||||
self.data_type = ViewDataType::TextBlock;
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
@ -409,7 +409,7 @@ impl ::protobuf::Message for View {
|
||||
if !self.desc.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(4, &self.desc);
|
||||
}
|
||||
if self.data_type != ViewDataType::Block {
|
||||
if self.data_type != ViewDataType::TextBlock {
|
||||
my_size += ::protobuf::rt::enum_size(5, self.data_type);
|
||||
}
|
||||
if self.version != 0 {
|
||||
@ -452,7 +452,7 @@ impl ::protobuf::Message for View {
|
||||
if !self.desc.is_empty() {
|
||||
os.write_string(4, &self.desc)?;
|
||||
}
|
||||
if self.data_type != ViewDataType::Block {
|
||||
if self.data_type != ViewDataType::TextBlock {
|
||||
os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?;
|
||||
}
|
||||
if self.version != 0 {
|
||||
@ -596,7 +596,7 @@ impl ::protobuf::Clear for View {
|
||||
self.belong_to_id.clear();
|
||||
self.name.clear();
|
||||
self.desc.clear();
|
||||
self.data_type = ViewDataType::Block;
|
||||
self.data_type = ViewDataType::TextBlock;
|
||||
self.version = 0;
|
||||
self.belongings.clear();
|
||||
self.modified_time = 0;
|
||||
@ -952,7 +952,7 @@ impl CreateViewPayload {
|
||||
self.data_type
|
||||
}
|
||||
pub fn clear_data_type(&mut self) {
|
||||
self.data_type = ViewDataType::Block;
|
||||
self.data_type = ViewDataType::TextBlock;
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
@ -1060,7 +1060,7 @@ impl ::protobuf::Message for CreateViewPayload {
|
||||
if !self.desc.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(3, &self.desc);
|
||||
}
|
||||
if self.data_type != ViewDataType::Block {
|
||||
if self.data_type != ViewDataType::TextBlock {
|
||||
my_size += ::protobuf::rt::enum_size(5, self.data_type);
|
||||
}
|
||||
if !self.ext_data.is_empty() {
|
||||
@ -1091,7 +1091,7 @@ impl ::protobuf::Message for CreateViewPayload {
|
||||
if !self.desc.is_empty() {
|
||||
os.write_string(3, &self.desc)?;
|
||||
}
|
||||
if self.data_type != ViewDataType::Block {
|
||||
if self.data_type != ViewDataType::TextBlock {
|
||||
os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?;
|
||||
}
|
||||
if !self.ext_data.is_empty() {
|
||||
@ -1200,7 +1200,7 @@ impl ::protobuf::Clear for CreateViewPayload {
|
||||
self.name.clear();
|
||||
self.desc.clear();
|
||||
self.one_of_thumbnail = ::std::option::Option::None;
|
||||
self.data_type = ViewDataType::Block;
|
||||
self.data_type = ViewDataType::TextBlock;
|
||||
self.ext_data.clear();
|
||||
self.plugin_type = 0;
|
||||
self.unknown_fields.clear();
|
||||
@ -1358,7 +1358,7 @@ impl CreateViewParams {
|
||||
self.data_type
|
||||
}
|
||||
pub fn clear_data_type(&mut self) {
|
||||
self.data_type = ViewDataType::Block;
|
||||
self.data_type = ViewDataType::TextBlock;
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
@ -1524,7 +1524,7 @@ impl ::protobuf::Message for CreateViewParams {
|
||||
if !self.thumbnail.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(4, &self.thumbnail);
|
||||
}
|
||||
if self.data_type != ViewDataType::Block {
|
||||
if self.data_type != ViewDataType::TextBlock {
|
||||
my_size += ::protobuf::rt::enum_size(5, self.data_type);
|
||||
}
|
||||
if !self.ext_data.is_empty() {
|
||||
@ -1557,7 +1557,7 @@ impl ::protobuf::Message for CreateViewParams {
|
||||
if !self.thumbnail.is_empty() {
|
||||
os.write_string(4, &self.thumbnail)?;
|
||||
}
|
||||
if self.data_type != ViewDataType::Block {
|
||||
if self.data_type != ViewDataType::TextBlock {
|
||||
os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?;
|
||||
}
|
||||
if !self.ext_data.is_empty() {
|
||||
@ -1675,7 +1675,7 @@ impl ::protobuf::Clear for CreateViewParams {
|
||||
self.name.clear();
|
||||
self.desc.clear();
|
||||
self.thumbnail.clear();
|
||||
self.data_type = ViewDataType::Block;
|
||||
self.data_type = ViewDataType::TextBlock;
|
||||
self.ext_data.clear();
|
||||
self.view_id.clear();
|
||||
self.data.clear();
|
||||
@ -2821,7 +2821,7 @@ impl ::protobuf::reflect::ProtobufValue for UpdateViewParams {
|
||||
|
||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||
pub enum ViewDataType {
|
||||
Block = 0,
|
||||
TextBlock = 0,
|
||||
Grid = 1,
|
||||
}
|
||||
|
||||
@ -2832,7 +2832,7 @@ impl ::protobuf::ProtobufEnum for ViewDataType {
|
||||
|
||||
fn from_i32(value: i32) -> ::std::option::Option<ViewDataType> {
|
||||
match value {
|
||||
0 => ::std::option::Option::Some(ViewDataType::Block),
|
||||
0 => ::std::option::Option::Some(ViewDataType::TextBlock),
|
||||
1 => ::std::option::Option::Some(ViewDataType::Grid),
|
||||
_ => ::std::option::Option::None
|
||||
}
|
||||
@ -2840,7 +2840,7 @@ impl ::protobuf::ProtobufEnum for ViewDataType {
|
||||
|
||||
fn values() -> &'static [Self] {
|
||||
static values: &'static [ViewDataType] = &[
|
||||
ViewDataType::Block,
|
||||
ViewDataType::TextBlock,
|
||||
ViewDataType::Grid,
|
||||
];
|
||||
values
|
||||
@ -2859,7 +2859,7 @@ impl ::std::marker::Copy for ViewDataType {
|
||||
|
||||
impl ::std::default::Default for ViewDataType {
|
||||
fn default() -> Self {
|
||||
ViewDataType::Block
|
||||
ViewDataType::TextBlock
|
||||
}
|
||||
}
|
||||
|
||||
@ -2904,8 +2904,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\
|
||||
\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\
|
||||
\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\
|
||||
\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail*#\n\x0cVi\
|
||||
ewDataType\x12\t\n\x05Block\x10\0\x12\x08\n\x04Grid\x10\x01b\x06proto3\
|
||||
\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail*'\n\x0cVi\
|
||||
ewDataType\x12\r\n\tTextBlock\x10\0\x12\x08\n\x04Grid\x10\x01b\x06proto3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||
|
@ -56,6 +56,6 @@ message UpdateViewParams {
|
||||
oneof one_of_thumbnail { string thumbnail = 4; };
|
||||
}
|
||||
enum ViewDataType {
|
||||
Block = 0;
|
||||
TextBlock = 0;
|
||||
Grid = 1;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ fn create_default_view(app_id: String, time: chrono::DateTime<Utc>) -> View {
|
||||
let view_id = uuid::Uuid::new_v4();
|
||||
let name = "Read me".to_string();
|
||||
let desc = "".to_string();
|
||||
let data_type = ViewDataType::Block;
|
||||
let data_type = ViewDataType::TextBlock;
|
||||
|
||||
View {
|
||||
id: view_id.to_string(),
|
||||
|
@ -30,6 +30,15 @@ pub struct GridBlock {
|
||||
pub row_count: i32,
|
||||
}
|
||||
|
||||
impl GridBlock {
|
||||
pub fn new() -> Self {
|
||||
GridBlock {
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GridBlockChangeset {
|
||||
pub block_id: String,
|
||||
pub start_row_index: Option<i32>,
|
||||
@ -73,9 +82,9 @@ pub struct Field {
|
||||
}
|
||||
|
||||
impl Field {
|
||||
pub fn new(id: &str, name: &str, desc: &str, field_type: FieldType) -> Self {
|
||||
pub fn new(name: &str, desc: &str, field_type: FieldType) -> Self {
|
||||
Self {
|
||||
id: id.to_owned(),
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
name: name.to_string(),
|
||||
desc: desc.to_string(),
|
||||
field_type,
|
||||
@ -224,14 +233,14 @@ pub struct RowMeta {
|
||||
}
|
||||
|
||||
impl RowMeta {
|
||||
pub fn new(id: &str, block_id: &str, cells: Vec<CellMeta>) -> Self {
|
||||
pub fn new(block_id: &str, cells: Vec<CellMeta>) -> Self {
|
||||
let cell_by_field_id = cells
|
||||
.into_iter()
|
||||
.map(|cell| (cell.id.clone(), cell))
|
||||
.collect::<HashMap<String, CellMeta>>();
|
||||
|
||||
Self {
|
||||
id: id.to_owned(),
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
block_id: block_id.to_owned(),
|
||||
cell_by_field_id,
|
||||
height: DEFAULT_ROW_HEIGHT,
|
||||
|
@ -32,7 +32,9 @@ fn grid_default_serde_test() {
|
||||
}
|
||||
|
||||
fn create_field(field_id: &str) -> Field {
|
||||
Field::new(field_id, "Text Field", "", FieldType::RichText)
|
||||
let mut field = Field::new("Text Field", "", FieldType::RichText);
|
||||
field.id = field_id.to_string();
|
||||
field
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
Loading…
Reference in New Issue
Block a user