mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add group action handler to intercept the create row progress
This commit is contained in:
parent
dc53cb00dd
commit
f0914cd6f1
@ -146,9 +146,9 @@ pub struct GridBlockChangesetPB {
|
||||
pub hide_rows: Vec<String>,
|
||||
}
|
||||
impl GridBlockChangesetPB {
|
||||
pub fn insert(block_id: &str, inserted_rows: Vec<InsertedRowPB>) -> Self {
|
||||
pub fn insert(block_id: String, inserted_rows: Vec<InsertedRowPB>) -> Self {
|
||||
Self {
|
||||
block_id: block_id.to_owned(),
|
||||
block_id,
|
||||
inserted_rows,
|
||||
..Default::default()
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_error::ErrorCode;
|
||||
use flowy_grid_data_model::parser::NotEmptyStr;
|
||||
|
||||
#[derive(ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct CreateBoardCardPayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub grid_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub group_id: String,
|
||||
}
|
||||
pub struct CreateBoardCardParams {
|
||||
pub grid_id: String,
|
||||
pub group_id: String,
|
||||
}
|
||||
|
||||
impl TryInto<CreateBoardCardParams> for CreateBoardCardPayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<CreateBoardCardParams, Self::Error> {
|
||||
let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
|
||||
let group_id = NotEmptyStr::parse(self.group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?;
|
||||
Ok(CreateBoardCardParams {
|
||||
grid_id: grid_id.0,
|
||||
group_id: group_id.0,
|
||||
})
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
mod board_card;
|
||||
mod configuration;
|
||||
mod group;
|
||||
|
||||
pub use board_card::*;
|
||||
pub use configuration::*;
|
||||
pub use group::*;
|
||||
|
@ -416,3 +416,14 @@ pub(crate) async fn get_groups_handler(
|
||||
let group = editor.load_groups().await?;
|
||||
data_result(group)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, manager), err)]
|
||||
pub(crate) async fn create_board_card_handler(
|
||||
data: Data<CreateBoardCardPayloadPB>,
|
||||
manager: AppData<Arc<GridManager>>,
|
||||
) -> DataResult<RowPB, FlowyError> {
|
||||
let params: CreateBoardCardParams = data.into_inner().try_into()?;
|
||||
let editor = manager.get_grid_editor(params.grid_id.as_ref())?;
|
||||
let row = editor.create_board_card().await?;
|
||||
data_result(row)
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
|
||||
// Date
|
||||
.event(GridEvent::UpdateDateCell, update_date_cell_handler)
|
||||
// Group
|
||||
.event(GridEvent::CreateBoardCard, create_row_handler)
|
||||
.event(GridEvent::GetGroup, get_groups_handler);
|
||||
|
||||
module
|
||||
@ -209,4 +210,7 @@ pub enum GridEvent {
|
||||
|
||||
#[event(input = "GridIdPB", output = "RepeatedGridGroupPB")]
|
||||
GetGroup = 100,
|
||||
|
||||
#[event(input = "CreateBoardCardPayloadPB", output = "RowPB")]
|
||||
CreateBoardCard = 110,
|
||||
}
|
||||
|
@ -62,22 +62,16 @@ impl GridBlockManager {
|
||||
Ok(self.get_editor(&block_id).await?)
|
||||
}
|
||||
|
||||
pub(crate) async fn create_row(
|
||||
&self,
|
||||
block_id: &str,
|
||||
row_rev: RowRevision,
|
||||
start_row_id: Option<String>,
|
||||
) -> FlowyResult<i32> {
|
||||
pub(crate) async fn create_row(&self, row_rev: RowRevision, start_row_id: Option<String>) -> FlowyResult<i32> {
|
||||
let block_id = row_rev.block_id.clone();
|
||||
let _ = self.persistence.insert(&row_rev.block_id, &row_rev.id)?;
|
||||
let editor = self.get_editor(&row_rev.block_id).await?;
|
||||
|
||||
let mut index_row_order = InsertedRowPB::from(&row_rev);
|
||||
let (row_count, row_index) = editor.create_row(row_rev, start_row_id).await?;
|
||||
index_row_order.index = row_index;
|
||||
|
||||
let _ = self
|
||||
.notify_did_update_block(block_id, GridBlockChangesetPB::insert(block_id, vec![index_row_order]))
|
||||
.await?;
|
||||
let changeset = GridBlockChangesetPB::insert(block_id.clone(), vec![index_row_order]);
|
||||
let _ = self.notify_did_update_block(&block_id, changeset).await?;
|
||||
Ok(row_count)
|
||||
}
|
||||
|
||||
@ -98,10 +92,16 @@ impl GridBlockManager {
|
||||
row_order.index = index;
|
||||
inserted_row_orders.push(row_order);
|
||||
}
|
||||
changesets.push(GridBlockMetaRevisionChangeset::from_row_count(&block_id, row_count));
|
||||
changesets.push(GridBlockMetaRevisionChangeset::from_row_count(
|
||||
block_id.clone(),
|
||||
row_count,
|
||||
));
|
||||
|
||||
let _ = self
|
||||
.notify_did_update_block(&block_id, GridBlockChangesetPB::insert(&block_id, inserted_row_orders))
|
||||
.notify_did_update_block(
|
||||
&block_id,
|
||||
GridBlockChangesetPB::insert(block_id.clone(), inserted_row_orders),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ impl GridBlockManager {
|
||||
.map(|row_info| Cow::Owned(row_info.row_id().to_owned()))
|
||||
.collect::<Vec<Cow<String>>>();
|
||||
let row_count = editor.delete_rows(row_ids).await?;
|
||||
let changeset = GridBlockMetaRevisionChangeset::from_row_count(&grid_block.id, row_count);
|
||||
let changeset = GridBlockMetaRevisionChangeset::from_row_count(grid_block.id.clone(), row_count);
|
||||
changesets.push(changeset);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ pub struct GridRevisionEditor {
|
||||
pub(crate) filter_service: Arc<GridFilterService>,
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) group_service: Arc<GridGroupService>,
|
||||
pub(crate) group_service: Arc<RwLock<GridGroupService>>,
|
||||
}
|
||||
|
||||
impl Drop for GridRevisionEditor {
|
||||
@ -62,17 +62,17 @@ impl GridRevisionEditor {
|
||||
let block_meta_revs = grid_pad.read().await.get_block_meta_revs();
|
||||
let block_manager = Arc::new(GridBlockManager::new(grid_id, &user, block_meta_revs, persistence).await?);
|
||||
let filter_service =
|
||||
Arc::new(GridFilterService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await);
|
||||
GridFilterService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await;
|
||||
let group_service =
|
||||
Arc::new(GridGroupService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await);
|
||||
GridGroupService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await;
|
||||
let editor = Arc::new(Self {
|
||||
grid_id: grid_id.to_owned(),
|
||||
user,
|
||||
grid_pad,
|
||||
rev_manager,
|
||||
block_manager,
|
||||
filter_service,
|
||||
group_service,
|
||||
filter_service: Arc::new(filter_service),
|
||||
group_service: Arc::new(RwLock::new(group_service)),
|
||||
});
|
||||
|
||||
Ok(editor)
|
||||
@ -275,20 +275,8 @@ impl GridRevisionEditor {
|
||||
}
|
||||
|
||||
pub async fn create_row(&self, start_row_id: Option<String>) -> FlowyResult<RowPB> {
|
||||
let field_revs = self.grid_pad.read().await.get_field_revs(None)?;
|
||||
let block_id = self.block_id().await?;
|
||||
|
||||
// insert empty row below the row whose id is upper_row_id
|
||||
let row_rev = RowRevisionBuilder::new(&block_id, &field_revs).build();
|
||||
let row_order = RowPB::from(&row_rev);
|
||||
|
||||
// insert the row
|
||||
let row_count = self.block_manager.create_row(&block_id, row_rev, start_row_id).await?;
|
||||
|
||||
// update block row count
|
||||
let changeset = GridBlockMetaRevisionChangeset::from_row_count(&block_id, row_count);
|
||||
let _ = self.update_block(changeset).await?;
|
||||
Ok(row_order)
|
||||
let row_rev = self.create_row_rev().await?;
|
||||
self.create_row_pb(row_rev, start_row_id).await
|
||||
}
|
||||
|
||||
pub async fn insert_rows(&self, row_revs: Vec<RowRevision>) -> FlowyResult<Vec<RowPB>> {
|
||||
@ -564,12 +552,40 @@ impl GridRevisionEditor {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn create_board_card(&self) -> FlowyResult<RowPB> {
|
||||
let mut row_rev = self.create_row_rev().await?;
|
||||
let _ = self.group_service.write().await.create_board_card(&mut row_rev).await;
|
||||
self.create_row_pb(row_rev, None).await
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub async fn load_groups(&self) -> FlowyResult<RepeatedGridGroupPB> {
|
||||
let groups = self.group_service.load_groups().await.unwrap_or_default();
|
||||
let groups = self.group_service.write().await.load_groups().await.unwrap_or_default();
|
||||
Ok(RepeatedGridGroupPB { items: groups })
|
||||
}
|
||||
|
||||
async fn create_row_rev(&self) -> FlowyResult<RowRevision> {
|
||||
let field_revs = self.grid_pad.read().await.get_field_revs(None)?;
|
||||
let block_id = self.block_id().await?;
|
||||
|
||||
// insert empty row below the row whose id is upper_row_id
|
||||
let row_rev = RowRevisionBuilder::new(&block_id, &field_revs).build();
|
||||
Ok(row_rev)
|
||||
}
|
||||
|
||||
async fn create_row_pb(&self, row_rev: RowRevision, start_row_id: Option<String>) -> FlowyResult<RowPB> {
|
||||
let row_pb = RowPB::from(&row_rev);
|
||||
let block_id = row_rev.block_id.clone();
|
||||
|
||||
// insert the row
|
||||
let row_count = self.block_manager.create_row(row_rev, start_row_id).await?;
|
||||
|
||||
// update block row count
|
||||
let changeset = GridBlockMetaRevisionChangeset::from_row_count(block_id, row_count);
|
||||
let _ = self.update_block(changeset).await?;
|
||||
Ok(row_pb)
|
||||
}
|
||||
|
||||
async fn modify<F>(&self, f: F) -> FlowyResult<()>
|
||||
where
|
||||
F: for<'a> FnOnce(&'a mut GridRevisionPad) -> FlowyResult<Option<GridChangeset>>,
|
||||
|
@ -1,17 +1,43 @@
|
||||
use crate::entities::CheckboxGroupConfigurationPB;
|
||||
use crate::entities::{CheckboxGroupConfigurationPB, RowPB};
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::RowRevision;
|
||||
|
||||
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
|
||||
use crate::services::group::{Group, GroupAction, GroupCellContentProvider, GroupController, GroupGenerator};
|
||||
use crate::services::group::{
|
||||
Group, GroupActionHandler, GroupCellContentProvider, GroupController, GroupGenerator, Groupable,
|
||||
};
|
||||
|
||||
pub type CheckboxGroupController =
|
||||
GroupController<CheckboxGroupConfigurationPB, CheckboxTypeOptionPB, CheckboxGroupGenerator, CheckboxCellDataParser>;
|
||||
|
||||
impl Groupable for CheckboxGroupController {
|
||||
type CellDataType = CheckboxCellData;
|
||||
|
||||
fn can_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupActionHandler for CheckboxGroupController {
|
||||
fn get_groups(&self) -> Vec<Group> {
|
||||
self.groups()
|
||||
}
|
||||
|
||||
fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> {
|
||||
self.handle_row(row_rev)
|
||||
}
|
||||
|
||||
fn create_card(&self, row_rev: &mut RowRevision) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CheckboxGroupGenerator();
|
||||
impl GroupGenerator for CheckboxGroupGenerator {
|
||||
type ConfigurationType = CheckboxGroupConfigurationPB;
|
||||
type TypeOptionType = CheckboxTypeOptionPB;
|
||||
|
||||
fn gen_groups(
|
||||
fn generate_groups(
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
_type_option: &Option<Self::TypeOptionType>,
|
||||
_cell_content_provider: &dyn GroupCellContentProvider,
|
||||
@ -33,11 +59,3 @@ impl GroupGenerator for CheckboxGroupGenerator {
|
||||
vec![check_group, uncheck_group]
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupAction for CheckboxGroupController {
|
||||
type CellDataType = CheckboxCellData;
|
||||
|
||||
fn should_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,6 @@ use indexmap::IndexMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait GroupAction {
|
||||
type CellDataType;
|
||||
|
||||
fn should_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
|
||||
}
|
||||
|
||||
pub trait GroupCellContentProvider {
|
||||
/// We need to group the rows base on the deduplication cell content when the field type is
|
||||
/// RichText.
|
||||
@ -27,25 +21,47 @@ pub trait GroupGenerator {
|
||||
type ConfigurationType;
|
||||
type TypeOptionType;
|
||||
|
||||
fn gen_groups(
|
||||
fn generate_groups(
|
||||
configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
cell_content_provider: &dyn GroupCellContentProvider,
|
||||
) -> Vec<Group>;
|
||||
}
|
||||
|
||||
pub trait Groupable {
|
||||
type CellDataType;
|
||||
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
|
||||
}
|
||||
|
||||
pub trait GroupActionHandler: Send + Sync {
|
||||
fn get_groups(&self) -> Vec<Group>;
|
||||
fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()>;
|
||||
fn group_rows(&mut self, row_revs: &[Arc<RowRevision>]) -> FlowyResult<()> {
|
||||
for row_rev in row_revs {
|
||||
let _ = self.group_row(row_rev)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn create_card(&self, row_rev: &mut RowRevision);
|
||||
}
|
||||
|
||||
const DEFAULT_GROUP_ID: &str = "default_group";
|
||||
|
||||
pub struct GroupController<C, T, G, CP> {
|
||||
/// C: represents the group configuration structure
|
||||
/// T: the type option data deserializer that impl [TypeOptionDataDeserializer]
|
||||
/// G: the group container generator
|
||||
/// P: the parser that impl [CellBytesParser] for the CellBytes
|
||||
pub struct GroupController<C, T, G, P> {
|
||||
pub field_rev: Arc<FieldRevision>,
|
||||
pub groups: IndexMap<String, Group>,
|
||||
pub default_group: Group,
|
||||
groups: IndexMap<String, Group>,
|
||||
default_group: Group,
|
||||
pub type_option: Option<T>,
|
||||
pub configuration: Option<C>,
|
||||
group_action_phantom: PhantomData<G>,
|
||||
cell_parser_phantom: PhantomData<CP>,
|
||||
cell_parser_phantom: PhantomData<P>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Group {
|
||||
pub id: String,
|
||||
pub desc: String,
|
||||
@ -63,7 +79,7 @@ impl std::convert::From<Group> for GroupPB {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, T, G, CP> GroupController<C, T, G, CP>
|
||||
impl<C, T, G, P> GroupController<C, T, G, P>
|
||||
where
|
||||
C: TryFrom<Bytes, Error = protobuf::ProtobufError>,
|
||||
T: TypeOptionDataDeserializer,
|
||||
@ -80,7 +96,7 @@ where
|
||||
};
|
||||
let field_type_rev = field_rev.field_type_rev;
|
||||
let type_option = field_rev.get_type_option_entry::<T>(field_type_rev);
|
||||
let groups = G::gen_groups(&configuration, &type_option, cell_content_provider);
|
||||
let groups = G::generate_groups(&configuration, &type_option, cell_content_provider);
|
||||
|
||||
let default_group = Group {
|
||||
id: DEFAULT_GROUP_ID.to_owned(),
|
||||
@ -100,9 +116,9 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub fn take_groups(self) -> Vec<Group> {
|
||||
let default_group = self.default_group;
|
||||
let mut groups: Vec<Group> = self.groups.into_values().collect();
|
||||
pub fn groups(&self) -> Vec<Group> {
|
||||
let default_group = self.default_group.clone();
|
||||
let mut groups: Vec<Group> = self.groups.values().cloned().collect();
|
||||
if !default_group.rows.is_empty() {
|
||||
groups.push(default_group);
|
||||
}
|
||||
@ -110,25 +126,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, T, G, CP> GroupController<C, T, G, CP>
|
||||
impl<C, T, G, P> GroupController<C, T, G, P>
|
||||
where
|
||||
CP: CellBytesParser,
|
||||
Self: GroupAction<CellDataType = CP::Object>,
|
||||
P: CellBytesParser,
|
||||
Self: Groupable<CellDataType = P::Object>,
|
||||
{
|
||||
pub fn group_rows(&mut self, rows: &[Arc<RowRevision>]) -> FlowyResult<()> {
|
||||
pub fn handle_row(&mut self, row: &RowRevision) -> FlowyResult<()> {
|
||||
if self.configuration.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("group {} rows", rows.len());
|
||||
|
||||
for row in rows {
|
||||
if let Some(cell_rev) = row.cells.get(&self.field_rev.id) {
|
||||
let mut records: Vec<GroupRecord> = vec![];
|
||||
|
||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &self.field_rev);
|
||||
let cell_data = cell_bytes.parser::<CP>()?;
|
||||
let cell_data = cell_bytes.parser::<P>()?;
|
||||
for group in self.groups.values() {
|
||||
if self.should_group(&group.content, &cell_data) {
|
||||
if self.can_group(&group.content, &cell_data) {
|
||||
records.push(GroupRecord {
|
||||
row: row.into(),
|
||||
group_id: group.id.clone(),
|
||||
@ -148,8 +160,14 @@ where
|
||||
} else {
|
||||
self.default_group.rows.push(row.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn group_rows(&mut self, rows: &[Arc<RowRevision>]) -> FlowyResult<()> {
|
||||
for row in rows {
|
||||
let _ = self.handle_row(row)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
use crate::entities::SelectOptionGroupConfigurationPB;
|
||||
use crate::entities::{RowPB, SelectOptionGroupConfigurationPB};
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::RowRevision;
|
||||
|
||||
use crate::services::field::{
|
||||
MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB,
|
||||
};
|
||||
use crate::services::group::{Group, GroupAction, GroupCellContentProvider, GroupController, GroupGenerator};
|
||||
use crate::services::group::{
|
||||
Group, GroupActionHandler, GroupCellContentProvider, GroupController, GroupGenerator, Groupable,
|
||||
};
|
||||
|
||||
// SingleSelect
|
||||
pub type SingleSelectGroupController = GroupController<
|
||||
@ -13,11 +17,32 @@ pub type SingleSelectGroupController = GroupController<
|
||||
SelectOptionCellDataParser,
|
||||
>;
|
||||
|
||||
impl Groupable for SingleSelectGroupController {
|
||||
type CellDataType = SelectOptionCellDataPB;
|
||||
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||
cell_data.select_options.iter().any(|option| option.id == content)
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupActionHandler for SingleSelectGroupController {
|
||||
fn get_groups(&self) -> Vec<Group> {
|
||||
self.groups()
|
||||
}
|
||||
|
||||
fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> {
|
||||
self.handle_row(row_rev)
|
||||
}
|
||||
|
||||
fn create_card(&self, row_rev: &mut RowRevision) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SingleSelectGroupGenerator();
|
||||
impl GroupGenerator for SingleSelectGroupGenerator {
|
||||
type ConfigurationType = SelectOptionGroupConfigurationPB;
|
||||
type TypeOptionType = SingleSelectTypeOptionPB;
|
||||
fn gen_groups(
|
||||
fn generate_groups(
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
_cell_content_provider: &dyn GroupCellContentProvider,
|
||||
@ -38,13 +63,6 @@ impl GroupGenerator for SingleSelectGroupGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupAction for SingleSelectGroupController {
|
||||
type CellDataType = SelectOptionCellDataPB;
|
||||
fn should_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||
cell_data.select_options.iter().any(|option| option.id == content)
|
||||
}
|
||||
}
|
||||
|
||||
// MultiSelect
|
||||
pub type MultiSelectGroupController = GroupController<
|
||||
SelectOptionGroupConfigurationPB,
|
||||
@ -53,12 +71,33 @@ pub type MultiSelectGroupController = GroupController<
|
||||
SelectOptionCellDataParser,
|
||||
>;
|
||||
|
||||
impl Groupable for MultiSelectGroupController {
|
||||
type CellDataType = SelectOptionCellDataPB;
|
||||
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||
cell_data.select_options.iter().any(|option| option.id == content)
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupActionHandler for MultiSelectGroupController {
|
||||
fn get_groups(&self) -> Vec<Group> {
|
||||
self.groups()
|
||||
}
|
||||
|
||||
fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> {
|
||||
self.handle_row(row_rev)
|
||||
}
|
||||
|
||||
fn create_card(&self, row_rev: &mut RowRevision) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MultiSelectGroupGenerator();
|
||||
impl GroupGenerator for MultiSelectGroupGenerator {
|
||||
type ConfigurationType = SelectOptionGroupConfigurationPB;
|
||||
type TypeOptionType = MultiSelectTypeOptionPB;
|
||||
|
||||
fn gen_groups(
|
||||
fn generate_groups(
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
_cell_content_provider: &dyn GroupCellContentProvider,
|
||||
@ -78,10 +117,3 @@ impl GroupGenerator for MultiSelectGroupGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupAction for MultiSelectGroupController {
|
||||
type CellDataType = SelectOptionCellDataPB;
|
||||
fn should_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||
cell_data.select_options.iter().any(|option| option.id == content)
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
use crate::services::block_manager::GridBlockManager;
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
use crate::services::group::{
|
||||
CheckboxGroupController, Group, GroupCellContentProvider, MultiSelectGroupController, SingleSelectGroupController,
|
||||
CheckboxGroupController, Group, GroupActionHandler, GroupCellContentProvider, MultiSelectGroupController,
|
||||
SingleSelectGroupController,
|
||||
};
|
||||
|
||||
use crate::entities::{
|
||||
CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupPB, NumberGroupConfigurationPB,
|
||||
SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB,
|
||||
CheckboxGroupConfigurationPB, CreateBoardCardParams, DateGroupConfigurationPB, FieldType, GroupPB,
|
||||
NumberGroupConfigurationPB, RowPB, SelectOptionGroupConfigurationPB, TextGroupConfigurationPB,
|
||||
UrlGroupConfigurationPB,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use flowy_error::FlowyResult;
|
||||
@ -18,10 +20,9 @@ use tokio::sync::RwLock;
|
||||
pub(crate) struct GridGroupService {
|
||||
#[allow(dead_code)]
|
||||
scheduler: Arc<dyn GridServiceTaskScheduler>,
|
||||
#[allow(dead_code)]
|
||||
grid_pad: Arc<RwLock<GridRevisionPad>>,
|
||||
#[allow(dead_code)]
|
||||
block_manager: Arc<GridBlockManager>,
|
||||
group_action_handler: Option<Arc<RwLock<dyn GroupActionHandler>>>,
|
||||
}
|
||||
|
||||
impl GridGroupService {
|
||||
@ -35,14 +36,14 @@ impl GridGroupService {
|
||||
scheduler,
|
||||
grid_pad,
|
||||
block_manager,
|
||||
group_action_handler: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn load_groups(&self) -> Option<Vec<GroupPB>> {
|
||||
let grid_pad = self.grid_pad.read().await;
|
||||
let field_rev = find_group_field(grid_pad.fields()).unwrap();
|
||||
pub(crate) async fn load_groups(&mut self) -> Option<Vec<GroupPB>> {
|
||||
let field_rev = find_group_field(self.grid_pad.read().await.fields()).unwrap();
|
||||
let field_type: FieldType = field_rev.field_type_rev.into();
|
||||
let configuration = self.get_group_configuration(field_rev).await;
|
||||
let configuration = self.get_group_configuration(&field_rev).await;
|
||||
|
||||
let blocks = self.block_manager.get_block_snapshots(None).await.unwrap();
|
||||
let row_revs = blocks
|
||||
@ -51,19 +52,28 @@ impl GridGroupService {
|
||||
.flatten()
|
||||
.collect::<Vec<Arc<RowRevision>>>();
|
||||
|
||||
match self.build_groups(&field_type, field_rev, row_revs, configuration) {
|
||||
match self
|
||||
.build_groups(&field_type, &field_rev, row_revs, configuration)
|
||||
.await
|
||||
{
|
||||
Ok(groups) => Some(groups),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||
pub(crate) async fn create_board_card(&self, row_rev: &mut RowRevision) {
|
||||
if let Some(group_action_handler) = self.group_action_handler.as_ref() {
|
||||
group_action_handler.write().await.create_card(row_rev);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn get_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||
let grid_pad = self.grid_pad.read().await;
|
||||
let setting = grid_pad.get_setting_rev();
|
||||
let layout = &setting.layout;
|
||||
let configurations = setting.get_groups(layout, &field_rev.id, &field_rev.field_type_rev);
|
||||
match configurations {
|
||||
None => self.default_group_configuration(field_rev),
|
||||
None => default_group_configuration(field_rev),
|
||||
Some(mut configurations) => {
|
||||
assert_eq!(configurations.len(), 1);
|
||||
(&*configurations.pop().unwrap()).clone()
|
||||
@ -71,7 +81,67 @@ impl GridGroupService {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
async fn build_groups(
|
||||
&mut self,
|
||||
field_type: &FieldType,
|
||||
field_rev: &Arc<FieldRevision>,
|
||||
row_revs: Vec<Arc<RowRevision>>,
|
||||
configuration: GroupConfigurationRevision,
|
||||
) -> FlowyResult<Vec<GroupPB>> {
|
||||
match field_type {
|
||||
FieldType::RichText => {
|
||||
// let generator = GroupGenerator::<TextGroupConfigurationPB>::from_configuration(configuration);
|
||||
}
|
||||
FieldType::Number => {
|
||||
// let generator = GroupGenerator::<NumberGroupConfigurationPB>::from_configuration(configuration);
|
||||
}
|
||||
FieldType::DateTime => {
|
||||
// let generator = GroupGenerator::<DateGroupConfigurationPB>::from_configuration(configuration);
|
||||
}
|
||||
FieldType::SingleSelect => {
|
||||
let controller = SingleSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
self.group_action_handler = Some(Arc::new(RwLock::new(controller)));
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
let controller = MultiSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
self.group_action_handler = Some(Arc::new(RwLock::new(controller)));
|
||||
}
|
||||
FieldType::Checkbox => {
|
||||
let controller = CheckboxGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
self.group_action_handler = Some(Arc::new(RwLock::new(controller)));
|
||||
}
|
||||
FieldType::URL => {
|
||||
// let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
|
||||
}
|
||||
};
|
||||
|
||||
let mut groups = vec![];
|
||||
if let Some(group_action_handler) = self.group_action_handler.as_ref() {
|
||||
let mut write_guard = group_action_handler.write().await;
|
||||
let _ = write_guard.group_rows(&row_revs)?;
|
||||
groups = write_guard.get_groups();
|
||||
drop(write_guard);
|
||||
}
|
||||
|
||||
Ok(groups.into_iter().map(GroupPB::from).collect())
|
||||
}
|
||||
}
|
||||
|
||||
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.field_type_rev.into();
|
||||
field_type.can_be_group()
|
||||
})
|
||||
.cloned();
|
||||
field_rev
|
||||
}
|
||||
|
||||
impl GroupCellContentProvider for Arc<RwLock<GridRevisionPad>> {}
|
||||
|
||||
fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||
let field_type: FieldType = field_rev.field_type_rev.clone().into();
|
||||
let bytes: Bytes = match field_type {
|
||||
FieldType::RichText => TextGroupConfigurationPB::default().try_into().unwrap(),
|
||||
@ -89,61 +159,3 @@ impl GridGroupService {
|
||||
content: Some(bytes.to_vec()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
fn build_groups(
|
||||
&self,
|
||||
field_type: &FieldType,
|
||||
field_rev: &Arc<FieldRevision>,
|
||||
row_revs: Vec<Arc<RowRevision>>,
|
||||
configuration: GroupConfigurationRevision,
|
||||
) -> FlowyResult<Vec<GroupPB>> {
|
||||
let groups: Vec<Group> = match field_type {
|
||||
FieldType::RichText => {
|
||||
// let generator = GroupGenerator::<TextGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
FieldType::Number => {
|
||||
// let generator = GroupGenerator::<NumberGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
FieldType::DateTime => {
|
||||
// let generator = GroupGenerator::<DateGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
FieldType::SingleSelect => {
|
||||
let mut group_controller =
|
||||
SingleSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
let _ = group_controller.group_rows(&row_revs)?;
|
||||
group_controller.take_groups()
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
let mut group_controller =
|
||||
MultiSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
let _ = group_controller.group_rows(&row_revs)?;
|
||||
group_controller.take_groups()
|
||||
}
|
||||
FieldType::Checkbox => {
|
||||
let mut group_controller =
|
||||
CheckboxGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
let _ = group_controller.group_rows(&row_revs)?;
|
||||
group_controller.take_groups()
|
||||
}
|
||||
FieldType::URL => {
|
||||
// let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
|
||||
Ok(groups.into_iter().map(GroupPB::from).collect())
|
||||
}
|
||||
}
|
||||
|
||||
fn find_group_field(field_revs: &[Arc<FieldRevision>]) -> Option<&Arc<FieldRevision>> {
|
||||
field_revs.iter().find(|field_rev| {
|
||||
let field_type: FieldType = field_rev.field_type_rev.into();
|
||||
field_type.can_be_group()
|
||||
})
|
||||
}
|
||||
|
||||
impl GroupCellContentProvider for Arc<RwLock<GridRevisionPad>> {}
|
||||
|
@ -111,6 +111,9 @@ pub enum ErrorCode {
|
||||
#[display(fmt = "Field's type option data should not be empty")]
|
||||
TypeOptionDataIsEmpty = 450,
|
||||
|
||||
#[display(fmt = "Group id is empty")]
|
||||
GroupIdIsEmpty = 460,
|
||||
|
||||
#[display(fmt = "Invalid date time format")]
|
||||
InvalidDateTimeFormat = 500,
|
||||
|
||||
|
@ -88,9 +88,9 @@ pub struct GridBlockMetaRevisionChangeset {
|
||||
}
|
||||
|
||||
impl GridBlockMetaRevisionChangeset {
|
||||
pub fn from_row_count(block_id: &str, row_count: i32) -> Self {
|
||||
pub fn from_row_count(block_id: String, row_count: i32) -> Self {
|
||||
Self {
|
||||
block_id: block_id.to_string(),
|
||||
block_id,
|
||||
start_row_index: None,
|
||||
row_count: Some(row_count),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user