mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: support switch to multi select field
This commit is contained in:
@ -207,6 +207,10 @@ impl GridRevisionEditor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn group_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> {
|
pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> {
|
||||||
// let block_ids = self
|
// let block_ids = self
|
||||||
// .get_block_metas()
|
// .get_block_metas()
|
||||||
|
@ -6,7 +6,9 @@ use crate::entities::{
|
|||||||
};
|
};
|
||||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||||
use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
|
use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
|
||||||
use crate::services::group::{GroupConfigurationReader, GroupConfigurationWriter, GroupService};
|
use crate::services::group::{
|
||||||
|
make_group_controller, GroupConfigurationReader, GroupConfigurationWriter, GroupController, GroupService,
|
||||||
|
};
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{
|
||||||
gen_grid_filter_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision,
|
gen_grid_filter_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision,
|
||||||
@ -17,6 +19,7 @@ use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
|
|||||||
use flowy_sync::entities::revision::Revision;
|
use flowy_sync::entities::revision::Revision;
|
||||||
use lib_infra::future::{wrap_future, AFFuture, FutureResult};
|
use lib_infra::future::{wrap_future, AFFuture, FutureResult};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -30,9 +33,8 @@ pub struct GridViewRevisionEditor {
|
|||||||
rev_manager: Arc<RevisionManager>,
|
rev_manager: Arc<RevisionManager>,
|
||||||
field_delegate: Arc<dyn GridViewFieldDelegate>,
|
field_delegate: Arc<dyn GridViewFieldDelegate>,
|
||||||
row_delegate: Arc<dyn GridViewRowDelegate>,
|
row_delegate: Arc<dyn GridViewRowDelegate>,
|
||||||
group_service: Arc<RwLock<GroupService>>,
|
group_controller: Arc<RwLock<Box<dyn GroupController>>>,
|
||||||
scheduler: Arc<dyn GridServiceTaskScheduler>,
|
scheduler: Arc<dyn GridServiceTaskScheduler>,
|
||||||
did_load_group: AtomicBool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GridViewRevisionEditor {
|
impl GridViewRevisionEditor {
|
||||||
@ -53,15 +55,25 @@ impl GridViewRevisionEditor {
|
|||||||
let pad = Arc::new(RwLock::new(view_revision_pad));
|
let pad = Arc::new(RwLock::new(view_revision_pad));
|
||||||
let rev_manager = Arc::new(rev_manager);
|
let rev_manager = Arc::new(rev_manager);
|
||||||
|
|
||||||
|
// Load group
|
||||||
let configuration_reader = GroupConfigurationReaderImpl(pad.clone());
|
let configuration_reader = GroupConfigurationReaderImpl(pad.clone());
|
||||||
let configuration_writer = GroupConfigurationWriterImpl {
|
let configuration_writer = GroupConfigurationWriterImpl {
|
||||||
user_id: user_id.to_owned(),
|
user_id: user_id.to_owned(),
|
||||||
rev_manager: rev_manager.clone(),
|
rev_manager: rev_manager.clone(),
|
||||||
view_pad: pad.clone(),
|
view_pad: pad.clone(),
|
||||||
};
|
};
|
||||||
let group_service = GroupService::new(view_id.clone(), configuration_reader, configuration_writer).await;
|
let field_revs = field_delegate.get_field_revs().await;
|
||||||
|
let row_revs = row_delegate.gv_row_revs().await;
|
||||||
|
let group_controller = make_group_controller(
|
||||||
|
view_id.clone(),
|
||||||
|
field_revs,
|
||||||
|
row_revs,
|
||||||
|
configuration_reader,
|
||||||
|
configuration_writer,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let user_id = user_id.to_owned();
|
let user_id = user_id.to_owned();
|
||||||
let did_load_group = AtomicBool::new(false);
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
pad,
|
pad,
|
||||||
user_id,
|
user_id,
|
||||||
@ -70,8 +82,7 @@ impl GridViewRevisionEditor {
|
|||||||
scheduler,
|
scheduler,
|
||||||
field_delegate,
|
field_delegate,
|
||||||
row_delegate,
|
row_delegate,
|
||||||
group_service: Arc::new(RwLock::new(group_service)),
|
group_controller: Arc::new(RwLock::new(group_controller)),
|
||||||
did_load_group,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,33 +123,58 @@ impl GridViewRevisionEditor {
|
|||||||
|
|
||||||
pub(crate) async fn did_delete_row(&self, row_rev: &RowRevision) {
|
pub(crate) async fn did_delete_row(&self, row_rev: &RowRevision) {
|
||||||
// Send the group notification if the current view has groups;
|
// Send the group notification if the current view has groups;
|
||||||
|
let group_field_id = self.group_controller.read().await.field_id().to_owned();
|
||||||
|
let field_rev = self.field_delegate.get_field_rev(&group_field_id).await;
|
||||||
|
field_rev.and_then(|field_rev| {
|
||||||
if let Some(changesets) = self
|
if let Some(changesets) = self
|
||||||
.group_service
|
.group_controller
|
||||||
.write()
|
.write()
|
||||||
.await
|
.await
|
||||||
.did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
.did_delete_row(row_rev, &field_rev)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
for changeset in changesets {
|
for changeset in changesets {
|
||||||
self.notify_did_update_group(changeset).await;
|
self.notify_did_update_group(changeset).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) {
|
||||||
|
let changeset = self
|
||||||
|
.mut_group_controller(|group_controller, field_rev| async {
|
||||||
|
group_controller.did_update_row(row_rev, &field_rev).await
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some(changeset) = changeset {
|
||||||
|
for changeset in changesets {
|
||||||
|
self.notify_did_update_group(changeset).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) {
|
async fn mut_group_controller<F, O, T>(&self, f: F) -> Option<T>
|
||||||
if let Some(changesets) = self
|
where
|
||||||
.group_service
|
F: FnOnce(&mut Box<dyn GroupController>, Arc<FieldRevision>) -> O,
|
||||||
.write()
|
O: Future<Output = Option<T>> + Send + Sync + 'static,
|
||||||
.await
|
|
||||||
.did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
for changeset in changesets {
|
let group_field_id = self.group_controller.read().await.field_id().to_owned();
|
||||||
self.notify_did_update_group(changeset).await;
|
match self.field_delegate.get_field_rev(&group_field_id).await {
|
||||||
|
None => None,
|
||||||
|
Some(field_rev) => {
|
||||||
|
let mut write_guard = self.group_controller.write().await;
|
||||||
|
Some(f(&mut write_guard, field_rev).await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_group_field_rev(&self) -> Option<Arc<FieldRevision>> {
|
||||||
|
let group_field_id = self.group_controller.read().await.field_id().to_owned();
|
||||||
|
self.field_delegate.get_field_rev(&group_field_id).await
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn move_group_row(
|
pub(crate) async fn move_group_row(
|
||||||
&self,
|
&self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
|
@ -241,6 +241,74 @@ impl GroupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||||
|
pub async fn make_group_controller<R, W>(
|
||||||
|
view_id: String,
|
||||||
|
field_revs: Vec<Arc<FieldRevision>>,
|
||||||
|
row_revs: Vec<Arc<RowRevision>>,
|
||||||
|
configuration_reader: R,
|
||||||
|
configuration_writer: W,
|
||||||
|
) -> FlowyResult<Box<dyn GroupController>>
|
||||||
|
where
|
||||||
|
R: GroupConfigurationReader,
|
||||||
|
W: GroupConfigurationWriter,
|
||||||
|
{
|
||||||
|
let field_rev = find_group_field(&field_revs)?;
|
||||||
|
let field_type: FieldType = field_rev.ty.into();
|
||||||
|
let mut group_controller: Box<dyn GroupController>;
|
||||||
|
match field_type {
|
||||||
|
FieldType::RichText => {
|
||||||
|
// let generator = GroupGenerator::<TextGroupConfigurationPB>::from_configuration(configuration);
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
FieldType::Number => {
|
||||||
|
// let generator = GroupGenerator::<NumberGroupConfigurationPB>::from_configuration(configuration);
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
FieldType::DateTime => {
|
||||||
|
// let generator = GroupGenerator::<DateGroupConfigurationPB>::from_configuration(configuration);
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
FieldType::SingleSelect => {
|
||||||
|
let configuration = SelectOptionGroupConfiguration::new(
|
||||||
|
view_id,
|
||||||
|
field_rev.clone(),
|
||||||
|
configuration_reader,
|
||||||
|
configuration_writer,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let controller = SingleSelectGroupController::new(&field_rev, configuration).await?;
|
||||||
|
group_controller = Box::new(controller);
|
||||||
|
}
|
||||||
|
FieldType::MultiSelect => {
|
||||||
|
let configuration = SelectOptionGroupConfiguration::new(
|
||||||
|
view_id,
|
||||||
|
field_rev.clone(),
|
||||||
|
configuration_reader,
|
||||||
|
configuration_writer,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let controller = MultiSelectGroupController::new(&field_rev, configuration).await?;
|
||||||
|
group_controller = Box::new(controller);
|
||||||
|
}
|
||||||
|
FieldType::Checkbox => {
|
||||||
|
let configuration =
|
||||||
|
CheckboxGroupConfiguration::new(view_id, field_rev.clone(), configuration_reader, configuration_writer)
|
||||||
|
.await?;
|
||||||
|
let controller = CheckboxGroupController::new(&field_rev, configuration).await?;
|
||||||
|
group_controller = Box::new(controller);
|
||||||
|
}
|
||||||
|
FieldType::URL => {
|
||||||
|
// let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = group_controller.fill_groups(&row_revs, &field_rev)?;
|
||||||
|
|
||||||
|
Ok(group_controller)
|
||||||
|
}
|
||||||
|
|
||||||
fn find_group_field(field_revs: &[Arc<FieldRevision>]) -> Option<Arc<FieldRevision>> {
|
fn find_group_field(field_revs: &[Arc<FieldRevision>]) -> Option<Arc<FieldRevision>> {
|
||||||
let field_rev = field_revs
|
let field_rev = field_revs
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -6,6 +6,7 @@ mod entities;
|
|||||||
mod group_service;
|
mod group_service;
|
||||||
|
|
||||||
pub(crate) use configuration::*;
|
pub(crate) use configuration::*;
|
||||||
|
pub(crate) use controller::*;
|
||||||
pub(crate) use controller_impls::*;
|
pub(crate) use controller_impls::*;
|
||||||
pub(crate) use entities::*;
|
pub(crate) use entities::*;
|
||||||
pub(crate) use group_service::*;
|
pub(crate) use group_service::*;
|
||||||
|
@ -3,7 +3,8 @@ use flowy_grid::entities::{
|
|||||||
CreateRowParams, FieldChangesetParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB,
|
CreateRowParams, FieldChangesetParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB,
|
||||||
};
|
};
|
||||||
use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell};
|
use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell};
|
||||||
use flowy_grid_data_model::revision::RowChangeset;
|
use flowy_grid_data_model::revision::{FieldRevision, RowChangeset};
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::time::interval;
|
use tokio::time::interval;
|
||||||
|
|
||||||
@ -47,6 +48,9 @@ pub enum GroupScript {
|
|||||||
UpdateField {
|
UpdateField {
|
||||||
changeset: FieldChangesetParams,
|
changeset: FieldChangesetParams,
|
||||||
},
|
},
|
||||||
|
GroupField {
|
||||||
|
field_id: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GridGroupTest {
|
pub struct GridGroupTest {
|
||||||
@ -179,6 +183,9 @@ impl GridGroupTest {
|
|||||||
let mut interval = interval(Duration::from_millis(130));
|
let mut interval = interval(Duration::from_millis(130));
|
||||||
interval.tick().await;
|
interval.tick().await;
|
||||||
}
|
}
|
||||||
|
GroupScript::GroupField { field_id } => {
|
||||||
|
self.editor.group_field(&field_id).await.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +198,20 @@ impl GridGroupTest {
|
|||||||
let groups = self.group_at_index(group_index).await;
|
let groups = self.group_at_index(group_index).await;
|
||||||
groups.rows.get(row_index).unwrap().clone()
|
groups.rows.get(row_index).unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_multi_select_field(&self) -> Arc<FieldRevision> {
|
||||||
|
let field = self
|
||||||
|
.inner
|
||||||
|
.field_revs
|
||||||
|
.iter()
|
||||||
|
.find(|field_rev| {
|
||||||
|
let field_type: FieldType = field_rev.ty.into();
|
||||||
|
field_type.is_multi_select()
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
return field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for GridGroupTest {
|
impl std::ops::Deref for GridGroupTest {
|
||||||
|
@ -390,3 +390,12 @@ async fn group_update_field_test() {
|
|||||||
];
|
];
|
||||||
test.run_scripts(scripts).await;
|
test.run_scripts(scripts).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn group_multi_select_field_test() {
|
||||||
|
let mut test = GridGroupTest::new().await;
|
||||||
|
let multi_select_field = test.get_multi_select_field().await;
|
||||||
|
|
||||||
|
let scripts = vec![];
|
||||||
|
test.run_scripts(scripts).await;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user