mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: create the default group for grid
This commit is contained in:
parent
6a1b84a098
commit
44ad0a2623
@ -283,7 +283,12 @@ class IGridCellController<T, D> extends Equatable {
|
||||
_loadDataOperation?.cancel();
|
||||
_loadDataOperation = Timer(const Duration(milliseconds: 10), () {
|
||||
_cellDataLoader.loadData().then((data) {
|
||||
_cellsCache.insert(_cacheKey, GridCell(object: data));
|
||||
if (data != null) {
|
||||
_cellsCache.insert(_cacheKey, GridCell(object: data));
|
||||
} else {
|
||||
_cellsCache.remove(_cacheKey);
|
||||
}
|
||||
|
||||
_cellDataNotifier?.value = data;
|
||||
});
|
||||
});
|
||||
|
@ -221,8 +221,9 @@ impl DefaultFolderBuilder {
|
||||
initial_quill_delta_string()
|
||||
};
|
||||
let _ = view_controller.set_latest_view(&view.id);
|
||||
let layout_type = ViewLayoutTypePB::from(view.layout.clone());
|
||||
let _ = view_controller
|
||||
.create_view(&view.id, ViewDataTypePB::Text, Bytes::from(view_data))
|
||||
.create_view(&view.id, ViewDataTypePB::Text, layout_type, Bytes::from(view_data))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
@ -249,7 +250,13 @@ impl FolderManager {
|
||||
pub trait ViewDataProcessor {
|
||||
fn initialize(&self) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError>;
|
||||
fn create_container(
|
||||
&self,
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
layout: ViewLayoutTypePB,
|
||||
delta_data: Bytes,
|
||||
) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
|
||||
|
||||
@ -267,6 +274,7 @@ pub trait ViewDataProcessor {
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
data: Vec<u8>,
|
||||
layout: ViewLayoutTypePB,
|
||||
) -> FutureResult<Bytes, FlowyError>;
|
||||
|
||||
fn data_type(&self) -> ViewDataTypePB;
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub use crate::entities::view::ViewDataTypePB;
|
||||
use crate::entities::ViewInfoPB;
|
||||
use crate::entities::{ViewInfoPB, ViewLayoutTypePB};
|
||||
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||
use crate::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
@ -67,10 +67,20 @@ impl ViewController {
|
||||
params.view_content_data = view_data.to_vec();
|
||||
} else {
|
||||
let delta_data = processor
|
||||
.create_view_from_delta_data(&user_id, ¶ms.view_id, params.view_content_data.clone())
|
||||
.create_view_from_delta_data(
|
||||
&user_id,
|
||||
¶ms.view_id,
|
||||
params.view_content_data.clone(),
|
||||
params.layout.clone(),
|
||||
)
|
||||
.await?;
|
||||
let _ = self
|
||||
.create_view(¶ms.view_id, params.data_type.clone(), delta_data)
|
||||
.create_view(
|
||||
¶ms.view_id,
|
||||
params.data_type.clone(),
|
||||
params.layout.clone(),
|
||||
delta_data,
|
||||
)
|
||||
.await?;
|
||||
};
|
||||
|
||||
@ -84,6 +94,7 @@ impl ViewController {
|
||||
&self,
|
||||
view_id: &str,
|
||||
data_type: ViewDataTypePB,
|
||||
layout_type: ViewLayoutTypePB,
|
||||
delta_data: Bytes,
|
||||
) -> Result<(), FlowyError> {
|
||||
if delta_data.is_empty() {
|
||||
@ -91,7 +102,9 @@ impl ViewController {
|
||||
}
|
||||
let user_id = self.user.user_id()?;
|
||||
let processor = self.get_data_processor(data_type)?;
|
||||
let _ = processor.create_container(&user_id, view_id, delta_data).await?;
|
||||
let _ = processor
|
||||
.create_container(&user_id, view_id, layout_type, delta_data)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::entities::GridLayout;
|
||||
use crate::services::block_editor::GridBlockRevisionCompactor;
|
||||
use crate::services::grid_editor::{GridRevisionCompactor, GridRevisionEditor};
|
||||
use crate::services::grid_view_manager::make_grid_view_rev_manager;
|
||||
@ -178,6 +179,7 @@ impl GridManager {
|
||||
pub async fn make_grid_view_data(
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
layout: GridLayout,
|
||||
grid_manager: Arc<GridManager>,
|
||||
build_context: BuildGridContext,
|
||||
) -> FlowyResult<Bytes> {
|
||||
@ -208,7 +210,7 @@ pub async fn make_grid_view_data(
|
||||
let _ = grid_manager.create_grid(&grid_id, repeated_revision).await?;
|
||||
|
||||
// Create grid view
|
||||
let grid_view = GridViewRevision::new(grid_id, view_id.to_owned());
|
||||
let grid_view = GridViewRevision::new(grid_id, view_id.to_owned(), layout.into());
|
||||
let grid_view_delta = make_grid_view_delta(&grid_view);
|
||||
let grid_view_delta_bytes = grid_view_delta.json_bytes();
|
||||
let repeated_revision: RepeatedRevision =
|
||||
|
@ -277,6 +277,7 @@ impl GridViewRevisionEditor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||
if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
|
||||
let new_group_controller = new_group_controller_with_field_rev(
|
||||
@ -374,13 +375,14 @@ impl GridViewRevisionEditor {
|
||||
async fn new_group_controller(
|
||||
user_id: String,
|
||||
view_id: String,
|
||||
pad: Arc<RwLock<GridViewRevisionPad>>,
|
||||
view_rev_pad: Arc<RwLock<GridViewRevisionPad>>,
|
||||
rev_manager: Arc<RevisionManager>,
|
||||
field_delegate: Arc<dyn GridViewFieldDelegate>,
|
||||
row_delegate: Arc<dyn GridViewRowDelegate>,
|
||||
) -> FlowyResult<Box<dyn GroupController>> {
|
||||
let configuration_reader = GroupConfigurationReaderImpl(pad.clone());
|
||||
let configuration_reader = GroupConfigurationReaderImpl(view_rev_pad.clone());
|
||||
let field_revs = field_delegate.get_field_revs().await;
|
||||
let layout = view_rev_pad.read().await.layout();
|
||||
// Read the group field or find a new group field
|
||||
let field_rev = configuration_reader
|
||||
.get_configuration()
|
||||
@ -391,24 +393,24 @@ async fn new_group_controller(
|
||||
.find(|field_rev| field_rev.id == configuration.field_id)
|
||||
.cloned()
|
||||
})
|
||||
.unwrap_or_else(|| find_group_field(&field_revs).unwrap());
|
||||
.unwrap_or_else(|| find_group_field(&field_revs, &layout).unwrap());
|
||||
|
||||
new_group_controller_with_field_rev(user_id, view_id, pad, rev_manager, field_rev, row_delegate).await
|
||||
new_group_controller_with_field_rev(user_id, view_id, view_rev_pad, rev_manager, field_rev, row_delegate).await
|
||||
}
|
||||
|
||||
async fn new_group_controller_with_field_rev(
|
||||
user_id: String,
|
||||
view_id: String,
|
||||
pad: Arc<RwLock<GridViewRevisionPad>>,
|
||||
view_rev_pad: Arc<RwLock<GridViewRevisionPad>>,
|
||||
rev_manager: Arc<RevisionManager>,
|
||||
field_rev: Arc<FieldRevision>,
|
||||
row_delegate: Arc<dyn GridViewRowDelegate>,
|
||||
) -> FlowyResult<Box<dyn GroupController>> {
|
||||
let configuration_reader = GroupConfigurationReaderImpl(pad.clone());
|
||||
let configuration_reader = GroupConfigurationReaderImpl(view_rev_pad.clone());
|
||||
let configuration_writer = GroupConfigurationWriterImpl {
|
||||
user_id,
|
||||
rev_manager,
|
||||
view_pad: pad,
|
||||
view_pad: view_rev_pad,
|
||||
};
|
||||
let row_revs = row_delegate.gv_row_revs().await;
|
||||
make_group_controller(view_id, field_rev, row_revs, configuration_reader, configuration_writer).await
|
||||
|
@ -8,7 +8,7 @@ use crate::services::group::{
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{
|
||||
CheckboxGroupConfigurationRevision, DateGroupConfigurationRevision, FieldRevision, GroupConfigurationRevision,
|
||||
NumberGroupConfigurationRevision, RowRevision, SelectOptionGroupConfigurationRevision,
|
||||
LayoutRevision, NumberGroupConfigurationRevision, RowRevision, SelectOptionGroupConfigurationRevision,
|
||||
TextGroupConfigurationRevision, UrlGroupConfigurationRevision,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
@ -62,15 +62,17 @@ where
|
||||
Ok(group_controller)
|
||||
}
|
||||
|
||||
pub fn find_group_field(field_revs: &[Arc<FieldRevision>]) -> Option<Arc<FieldRevision>> {
|
||||
let field_rev = field_revs
|
||||
.iter()
|
||||
.find(|field_rev| {
|
||||
let field_type: FieldType = field_rev.ty.into();
|
||||
field_type.can_be_group()
|
||||
})
|
||||
.cloned();
|
||||
field_rev
|
||||
pub fn find_group_field(field_revs: &[Arc<FieldRevision>], layout: &LayoutRevision) -> Option<Arc<FieldRevision>> {
|
||||
match layout {
|
||||
LayoutRevision::Table => field_revs.iter().find(|field_rev| field_rev.is_primary).cloned(),
|
||||
LayoutRevision::Board => field_revs
|
||||
.iter()
|
||||
.find(|field_rev| {
|
||||
let field_type: FieldType = field_rev.ty.into();
|
||||
field_type.can_be_group()
|
||||
})
|
||||
.cloned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||
|
@ -7,6 +7,7 @@ use flowy_folder::{
|
||||
event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser},
|
||||
manager::FolderManager,
|
||||
};
|
||||
use flowy_grid::entities::GridLayout;
|
||||
use flowy_grid::manager::{make_grid_view_data, GridManager};
|
||||
use flowy_grid::util::{make_default_board, make_default_grid};
|
||||
use flowy_grid_data_model::revision::BuildGridContext;
|
||||
@ -142,7 +143,15 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
|
||||
FutureResult::new(async move { manager.init() })
|
||||
}
|
||||
|
||||
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError> {
|
||||
fn create_container(
|
||||
&self,
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
layout: ViewLayoutTypePB,
|
||||
delta_data: Bytes,
|
||||
) -> FutureResult<(), FlowyError> {
|
||||
// Only accept Document type
|
||||
debug_assert_eq!(layout, ViewLayoutTypePB::Document);
|
||||
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();
|
||||
@ -196,7 +205,9 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
|
||||
_user_id: &str,
|
||||
_view_id: &str,
|
||||
data: Vec<u8>,
|
||||
layout: ViewLayoutTypePB,
|
||||
) -> FutureResult<Bytes, FlowyError> {
|
||||
debug_assert_eq!(layout, ViewLayoutTypePB::Document);
|
||||
FutureResult::new(async move { Ok(Bytes::from(data)) })
|
||||
}
|
||||
|
||||
@ -211,7 +222,13 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
||||
FutureResult::new(async { Ok(()) })
|
||||
}
|
||||
|
||||
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError> {
|
||||
fn create_container(
|
||||
&self,
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
_layout: ViewLayoutTypePB,
|
||||
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();
|
||||
@ -246,19 +263,22 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
||||
view_id: &str,
|
||||
layout: ViewLayoutTypePB,
|
||||
) -> FutureResult<Bytes, FlowyError> {
|
||||
let build_context = match layout {
|
||||
ViewLayoutTypePB::Grid => make_default_grid(),
|
||||
ViewLayoutTypePB::Board => make_default_board(),
|
||||
let (build_context, layout) = match layout {
|
||||
ViewLayoutTypePB::Grid => (make_default_grid(), GridLayout::Table),
|
||||
ViewLayoutTypePB::Board => (make_default_board(), GridLayout::Board),
|
||||
ViewLayoutTypePB::Document => {
|
||||
return FutureResult::new(async move {
|
||||
Err(FlowyError::internal().context(format!("Can't handle {:?} layout type", layout)))
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let user_id = user_id.to_string();
|
||||
let view_id = view_id.to_string();
|
||||
let grid_manager = self.0.clone();
|
||||
FutureResult::new(async move { make_grid_view_data(&user_id, &view_id, grid_manager, build_context).await })
|
||||
FutureResult::new(
|
||||
async move { make_grid_view_data(&user_id, &view_id, layout, grid_manager, build_context).await },
|
||||
)
|
||||
}
|
||||
|
||||
fn create_view_from_delta_data(
|
||||
@ -266,15 +286,26 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
data: Vec<u8>,
|
||||
layout: ViewLayoutTypePB,
|
||||
) -> FutureResult<Bytes, FlowyError> {
|
||||
let user_id = user_id.to_string();
|
||||
let view_id = view_id.to_string();
|
||||
let grid_manager = self.0.clone();
|
||||
|
||||
let layout = match layout {
|
||||
ViewLayoutTypePB::Grid => GridLayout::Table,
|
||||
ViewLayoutTypePB::Board => GridLayout::Board,
|
||||
ViewLayoutTypePB::Document => {
|
||||
return FutureResult::new(async move {
|
||||
Err(FlowyError::internal().context(format!("Can't handle {:?} layout type", layout)))
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
FutureResult::new(async move {
|
||||
let bytes = Bytes::from(data);
|
||||
let build_context = BuildGridContext::try_from(bytes)?;
|
||||
make_grid_view_data(&user_id, &view_id, grid_manager, build_context).await
|
||||
make_grid_view_data(&user_id, &view_id, layout, grid_manager, build_context).await
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -48,11 +48,11 @@ pub struct GridViewRevision {
|
||||
}
|
||||
|
||||
impl GridViewRevision {
|
||||
pub fn new(grid_id: String, view_id: String) -> Self {
|
||||
pub fn new(grid_id: String, view_id: String, layout: LayoutRevision) -> Self {
|
||||
GridViewRevision {
|
||||
view_id,
|
||||
grid_id,
|
||||
layout: Default::default(),
|
||||
layout,
|
||||
filters: Default::default(),
|
||||
groups: Default::default(),
|
||||
// row_orders: vec![],
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::entities::revision::{md5, RepeatedRevision, Revision};
|
||||
use crate::errors::{internal_error, CollaborateError, CollaborateResult};
|
||||
use crate::errors::{internal_error, CollaborateError, CollaborateResult };
|
||||
use crate::util::{cal_diff, make_text_delta_from_revisions};
|
||||
use bytes::Bytes;
|
||||
use flowy_grid_data_model::revision::{
|
||||
@ -103,8 +103,12 @@ impl GridRevisionPad {
|
||||
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
|
||||
None => Ok(None),
|
||||
Some(index) => {
|
||||
grid_meta.fields.remove(index);
|
||||
Ok(Some(()))
|
||||
if grid_meta.fields[index].is_primary {
|
||||
Err(CollaborateError::can_not_delete_primary_field())
|
||||
} else {
|
||||
grid_meta.fields.remove(index);
|
||||
Ok(Some(()))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -3,7 +3,7 @@ use crate::errors::{internal_error, CollaborateError, CollaborateResult};
|
||||
use crate::util::{cal_diff, make_text_delta_from_revisions};
|
||||
use flowy_grid_data_model::revision::{
|
||||
FieldRevision, FieldTypeRevision, FilterConfigurationRevision, FilterConfigurationsByFieldId, GridViewRevision,
|
||||
GroupConfigurationRevision, GroupConfigurationsByFieldId,
|
||||
GroupConfigurationRevision, GroupConfigurationsByFieldId, LayoutRevision,
|
||||
};
|
||||
use lib_ot::core::{Delta, DeltaBuilder, EmptyAttributes, OperationTransform};
|
||||
use std::sync::Arc;
|
||||
@ -25,8 +25,8 @@ impl std::ops::Deref for GridViewRevisionPad {
|
||||
impl GridViewRevisionPad {
|
||||
// For the moment, the view_id is equal to grid_id. The grid_id represents the database id.
|
||||
// A database can be referenced by multiple views.
|
||||
pub fn new(grid_id: String, view_id: String) -> Self {
|
||||
let view = Arc::new(GridViewRevision::new(grid_id, view_id));
|
||||
pub fn new(grid_id: String, view_id: String, layout: LayoutRevision) -> Self {
|
||||
let view = Arc::new(GridViewRevision::new(grid_id, view_id, layout));
|
||||
let json = serde_json::to_string(&view).unwrap();
|
||||
let delta = DeltaBuilder::new().insert(&json).build();
|
||||
Self { view, delta }
|
||||
@ -34,7 +34,11 @@ impl GridViewRevisionPad {
|
||||
|
||||
pub fn from_delta(view_id: &str, delta: Delta) -> CollaborateResult<Self> {
|
||||
if delta.is_empty() {
|
||||
return Ok(GridViewRevisionPad::new(view_id.to_owned(), view_id.to_owned()));
|
||||
return Ok(GridViewRevisionPad::new(
|
||||
view_id.to_owned(),
|
||||
view_id.to_owned(),
|
||||
LayoutRevision::Table,
|
||||
));
|
||||
}
|
||||
let s = delta.content()?;
|
||||
let view: GridViewRevision = serde_json::from_str(&s).map_err(|e| {
|
||||
@ -163,6 +167,10 @@ impl GridViewRevisionPad {
|
||||
make_grid_view_rev_json_str(&self.view)
|
||||
}
|
||||
|
||||
pub fn layout(&self) -> LayoutRevision {
|
||||
self.layout.clone()
|
||||
}
|
||||
|
||||
fn modify<F>(&mut self, f: F) -> CollaborateResult<Option<GridViewRevisionChangeset>>
|
||||
where
|
||||
F: FnOnce(&mut GridViewRevision) -> CollaborateResult<Option<()>>,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{fmt, fmt::Debug};
|
||||
use strum_macros::Display;
|
||||
|
||||
macro_rules! static_doc_error {
|
||||
macro_rules! static_error {
|
||||
($name:ident, $status:expr) => {
|
||||
#[allow(non_snake_case, missing_docs)]
|
||||
pub fn $name() -> CollaborateError {
|
||||
@ -34,12 +34,13 @@ impl CollaborateError {
|
||||
self
|
||||
}
|
||||
|
||||
static_doc_error!(internal, ErrorCode::InternalError);
|
||||
static_doc_error!(undo, ErrorCode::UndoFail);
|
||||
static_doc_error!(redo, ErrorCode::RedoFail);
|
||||
static_doc_error!(out_of_bound, ErrorCode::OutOfBound);
|
||||
static_doc_error!(record_not_found, ErrorCode::RecordNotFound);
|
||||
static_doc_error!(revision_conflict, ErrorCode::RevisionConflict);
|
||||
static_error!(internal, ErrorCode::InternalError);
|
||||
static_error!(undo, ErrorCode::UndoFail);
|
||||
static_error!(redo, ErrorCode::RedoFail);
|
||||
static_error!(out_of_bound, ErrorCode::OutOfBound);
|
||||
static_error!(record_not_found, ErrorCode::RecordNotFound);
|
||||
static_error!(revision_conflict, ErrorCode::RevisionConflict);
|
||||
static_error!(can_not_delete_primary_field, ErrorCode::CannotDeleteThePrimaryField);
|
||||
}
|
||||
|
||||
impl fmt::Display for CollaborateError {
|
||||
@ -57,6 +58,7 @@ pub enum ErrorCode {
|
||||
OutOfBound = 202,
|
||||
RevisionConflict = 203,
|
||||
RecordNotFound = 300,
|
||||
CannotDeleteThePrimaryField = 301,
|
||||
InternalError = 1000,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user