소스 검색

chore: add group documentation (#1258)

Nathan.fooo 2 년 전
부모
커밋
4e122a9452

+ 9 - 10
frontend/rust-lib/flowy-grid/src/entities/field_entities.rs

@@ -250,13 +250,6 @@ impl TryInto<FieldTypeOptionIdParams> for FieldTypeOptionIdPB {
     }
 }
 
-/// Certain field types have user-defined options such as color, date format, number format,
-/// or a list of values for a multi-select list. These options are defined within a specialization
-/// of the FieldTypeOption class.
-///
-/// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
-/// for more information.
-///
 #[derive(Debug, Default, ProtoBuf)]
 pub struct FieldTypeOptionDataPB {
     #[pb(index = 1)]
@@ -510,7 +503,15 @@ pub struct FieldChangesetParams {
 
     pub type_option_data: Option<Vec<u8>>,
 }
-
+/// Certain field types have user-defined options such as color, date format, number format,
+/// or a list of values for a multi-select list. These options are defined within a specialization
+/// of the FieldTypeOption class.
+///
+/// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
+/// for more information.
+///
+/// The order of the enum can't be changed. If you want to add a new type,
+/// it would be better to append it to the end of the list.
 #[derive(
     Debug,
     Clone,
@@ -525,8 +526,6 @@ pub struct FieldChangesetParams {
     Serialize_repr,
     Deserialize_repr,
 )]
-/// The order of the enum can't be changed. If you want to add a new type,
-/// it would be better to append it to the end of the list.
 #[repr(u8)]
 pub enum FieldType {
     RichText = 0,

+ 24 - 21
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -193,7 +193,7 @@ impl GridRevisionEditor {
             .modify(|grid_pad| Ok(grid_pad.replace_field_rev(field_rev.clone())?))
             .await?;
 
-        match self.view_manager.did_update_field(&field_rev.id, false).await {
+        match self.view_manager.did_update_view_field(&field_rev.id).await {
             Ok(_) => {}
             Err(e) => tracing::error!("View manager update field failed: {:?}", e),
         }
@@ -214,27 +214,28 @@ impl GridRevisionEditor {
         Ok(())
     }
 
+    /// Switch the field with id to a new field type.  
+    ///
+    /// If the field type is not exist before, the default type option data will be created.
+    /// Each field type has its corresponding data, aka, the type option data. Check out [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
+    /// for more information
+    ///
+    /// # Arguments
+    ///
+    /// * `field_id`: the id of the field
+    /// * `field_type`: the new field type of the field
+    ///
     pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> {
-        // let block_ids = self
-        //     .get_block_metas()
-        //     .await?
-        //     .into_iter()
-        //     .map(|block_meta| block_meta.block_id)
-        //     .collect();
-        // let cell_revs = self
-        //     .block_meta_manager
-        //     .get_cell_revs(block_ids, field_id, None)
-        //     .await?;
-
-        let type_option_json_builder = |field_type: &FieldTypeRevision| -> String {
+        let type_option_builder = |field_type: &FieldTypeRevision| -> String {
             let field_type: FieldType = field_type.into();
+
             return default_type_option_builder_from_type(&field_type)
                 .data_format()
                 .json_str();
         };
 
         let _ = self
-            .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?))
+            .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_builder)?))
             .await?;
 
         let _ = self.notify_did_update_grid_field(field_id).await?;
@@ -276,6 +277,7 @@ impl GridRevisionEditor {
         Ok(field_revs)
     }
 
+    #[tracing::instrument(level = "debug", skip_all, err)]
     async fn update_field_rev(&self, params: FieldChangesetParams, field_type: FieldType) -> FlowyResult<()> {
         let mut is_type_option_changed = false;
         let _ = self
@@ -333,14 +335,15 @@ impl GridRevisionEditor {
             })
             .await?;
 
-        match self
-            .view_manager
-            .did_update_field(&params.field_id, is_type_option_changed)
-            .await
-        {
-            Ok(_) => {}
-            Err(e) => tracing::error!("View manager update field failed: {:?}", e),
+        if is_type_option_changed {
+            let _ = self
+                .view_manager
+                .did_update_view_field_type_option(&params.field_id)
+                .await?;
+        } else {
+            let _ = self.view_manager.did_update_view_field(&params.field_id).await?;
         }
+
         Ok(())
     }
 

+ 28 - 6
frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs

@@ -118,7 +118,9 @@ impl GridViewRevisionEditor {
     pub(crate) async fn did_delete_view_row(&self, row_rev: &RowRevision) {
         // Send the group notification if the current view has groups;
         let changesets = self
-            .mut_group_controller(|group_controller, field_rev| group_controller.did_delete_row(row_rev, &field_rev))
+            .mut_group_controller(|group_controller, field_rev| {
+                group_controller.did_delete_delete_row(row_rev, &field_rev)
+            })
             .await;
 
         if let Some(changesets) = changesets {
@@ -131,7 +133,9 @@ impl GridViewRevisionEditor {
 
     pub(crate) async fn did_update_view_row(&self, row_rev: &RowRevision) {
         let changesets = self
-            .mut_group_controller(|group_controller, field_rev| group_controller.did_update_row(row_rev, &field_rev))
+            .mut_group_controller(|group_controller, field_rev| {
+                group_controller.did_update_group_row(row_rev, &field_rev)
+            })
             .await;
 
         if let Some(changesets) = changesets {
@@ -239,7 +243,7 @@ impl GridViewRevisionEditor {
                 .await?;
         }
         if self.group_controller.read().await.field_id() != params.field_id {
-            let _ = self.group_by_field(&params.field_id).await?;
+            let _ = self.group_by_view_field(&params.field_id).await?;
             self.notify_did_update_setting().await;
         }
         Ok(())
@@ -279,9 +283,9 @@ impl GridViewRevisionEditor {
         .await
     }
     #[tracing::instrument(level = "trace", skip_all, err)]
-    pub(crate) async fn did_update_field(&self, field_id: &str) -> FlowyResult<()> {
+    pub(crate) async fn did_update_view_field(&self, field_id: &str) -> FlowyResult<()> {
         if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
-            match self.group_controller.write().await.did_update_field(&field_rev)? {
+            match self.group_controller.write().await.did_update_group_field(&field_rev)? {
                 None => {}
                 Some(changeset) => {
                     self.notify_did_update_view(changeset).await;
@@ -291,8 +295,14 @@ impl GridViewRevisionEditor {
         Ok(())
     }
 
+    ///
+    ///
+    /// # Arguments
+    ///
+    /// * `field_id`:
+    ///
     #[tracing::instrument(level = "debug", skip_all, err)]
-    pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
+    pub(crate) async fn group_by_view_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(
                 self.user_id.clone(),
@@ -386,6 +396,7 @@ impl GridViewRevisionEditor {
         }
     }
 }
+
 async fn new_group_controller(
     user_id: String,
     view_id: String,
@@ -412,6 +423,17 @@ async fn new_group_controller(
     new_group_controller_with_field_rev(user_id, view_id, view_rev_pad, rev_manager, field_rev, row_delegate).await
 }
 
+/// Returns a [GroupController]  
+///
+/// # Arguments
+///
+/// * `user_id`:
+/// * `view_id`:
+/// * `view_rev_pad`:
+/// * `rev_manager`:
+/// * `field_rev`:
+/// * `row_delegate`:
+///
 async fn new_group_controller_with_field_rev(
     user_id: String,
     view_id: String,

+ 17 - 7
frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs

@@ -93,7 +93,7 @@ impl GridViewManager {
 
     pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
         let view_editor = self.get_default_view_editor().await?;
-        let _ = view_editor.group_by_field(field_id).await?;
+        let _ = view_editor.group_by_view_field(field_id).await?;
         Ok(())
     }
 
@@ -177,18 +177,28 @@ impl GridViewManager {
     }
 
     #[tracing::instrument(level = "trace", skip(self), err)]
-    pub(crate) async fn did_update_field(&self, field_id: &str, is_type_option_changed: bool) -> FlowyResult<()> {
+    pub(crate) async fn did_update_view_field(&self, field_id: &str) -> FlowyResult<()> {
         let view_editor = self.get_default_view_editor().await?;
         // Only the field_id of the updated field is equal to the field_id of the group.
         // Update the group
         if view_editor.group_id().await != field_id {
             return Ok(());
         }
-        if is_type_option_changed {
-            let _ = view_editor.group_by_field(field_id).await?;
-        } else {
-            let _ = view_editor.did_update_field(field_id).await?;
-        }
+        let _ = view_editor.did_update_view_field(field_id).await?;
+        Ok(())
+    }
+
+    /// Notifies the view's field type option data is changed
+    /// For the moment, only the groups will be generated after the type option data changed. A
+    /// [FieldRevision] has a property named type_options contains a list of type option data.
+    /// # Arguments
+    ///
+    /// * `field_id`: the id of the field in current view
+    ///
+    #[tracing::instrument(level = "trace", skip(self), err)]
+    pub(crate) async fn did_update_view_field_type_option(&self, field_id: &str) -> FlowyResult<()> {
+        let view_editor = self.get_default_view_editor().await?;
+        let _ = view_editor.group_by_view_field(field_id).await?;
         Ok(())
     }
 

+ 64 - 40
frontend/rust-lib/flowy-grid/src/services/group/configuration.rs

@@ -1,5 +1,5 @@
 use crate::entities::{GroupPB, GroupViewChangesetPB};
-use crate::services::group::{default_group_configuration, make_default_group, GeneratedGroup, Group};
+use crate::services::group::{default_group_configuration, make_no_status_group, GeneratedGroupConfig, Group};
 use flowy_error::{FlowyError, FlowyResult};
 use flowy_grid_data_model::revision::{
     FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision,
@@ -34,14 +34,28 @@ impl<T> std::fmt::Display for GroupContext<T> {
     }
 }
 
+/// A [GroupContext] represents as the groups memory cache
+/// Each [GenericGroupController] has its own [GroupContext], the `context` has its own configuration
+/// that is restored from the disk.
+///
+/// The `context` contains a list of [Group]s and the grouping [FieldRevision]
 pub struct GroupContext<C> {
     pub view_id: String,
+    /// The group configuration restored from the disk.
+    ///
+    /// Uses the [GroupConfigurationReader] to read the configuration data from disk
     configuration: Arc<GroupConfigurationRevision>,
-    configuration_content: PhantomData<C>,
+    configuration_phantom: PhantomData<C>,
+
+    /// The grouping field
     field_rev: Arc<FieldRevision>,
+
+    /// Cache all the groups
     groups_map: IndexMap<String, Group>,
-    /// default_group is used to store the rows that don't belong to any groups.
-    // default_group: Group,
+
+    /// A writer that implement the [GroupConfigurationWriter] trait is used to save the
+    /// configuration to disk  
+    ///
     writer: Arc<dyn GroupConfigurationWriter>,
 }
 
@@ -73,19 +87,21 @@ where
             groups_map: IndexMap::new(),
             writer,
             configuration,
-            configuration_content: PhantomData,
+            configuration_phantom: PhantomData,
         })
     }
 
-    pub(crate) fn get_default_group(&self) -> Option<&Group> {
+    /// Returns the no `status` group
+    ///
+    /// We take the `id` of the `field` as the default group id
+    pub(crate) fn get_no_status_group(&self) -> Option<&Group> {
         self.groups_map.get(&self.field_rev.id)
     }
 
-    pub(crate) fn get_mut_default_group(&mut self) -> Option<&mut Group> {
+    pub(crate) fn get_mut_no_status_group(&mut self) -> Option<&mut Group> {
         self.groups_map.get_mut(&self.field_rev.id)
     }
 
-    /// Returns the groups without the default group
     pub(crate) fn groups(&self) -> Vec<&Group> {
         self.groups_map.values().collect()
     }
@@ -142,23 +158,38 @@ where
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self, generated_groups), err)]
+    ///  Reset the memory cache of the groups and update the group configuration
+    ///
+    /// # Arguments
+    ///
+    /// * `generated_group_configs`: the generated groups contains a list of [GeneratedGroupConfig].
+    ///
+    /// Each [FieldType] can implement the [GroupGenerator] trait in order to generate different
+    /// groups. For example, the FieldType::Checkbox has the [CheckboxGroupGenerator] that implements
+    /// the [GroupGenerator] trait.
+    ///
+    /// Consider the passed-in generated_group_configs as new groups, the groups in the current
+    /// [GroupConfigurationRevision] as old groups. The old groups and the new groups will be merged
+    /// while keeping the order of the old groups.
+    ///
+    #[tracing::instrument(level = "debug", skip(self, generated_group_configs), err)]
     pub(crate) fn init_groups(
         &mut self,
-        generated_groups: Vec<GeneratedGroup>,
+        generated_group_configs: Vec<GeneratedGroupConfig>,
     ) -> FlowyResult<Option<GroupViewChangesetPB>> {
         let mut new_groups = vec![];
         let mut filter_content_map = HashMap::new();
-        generated_groups.into_iter().for_each(|generate_group| {
+        generated_group_configs.into_iter().for_each(|generate_group| {
             filter_content_map.insert(generate_group.group_rev.id.clone(), generate_group.filter_content);
             new_groups.push(generate_group.group_rev);
         });
 
         let mut old_groups = self.configuration.groups.clone();
         if !old_groups.iter().any(|group| group.id == self.field_rev.id) {
-            old_groups.push(make_default_group(&self.field_rev));
+            old_groups.push(make_no_status_group(&self.field_rev));
         }
 
+        // The `all_group_revs` represents as the combination of the new groups and old groups
         let MergeGroupResult {
             mut all_group_revs,
             new_group_revs,
@@ -171,6 +202,7 @@ where
             .map(|group_rev| group_rev.id)
             .collect::<Vec<String>>();
 
+        // Delete/Insert the group in the current configuration
         self.mut_configuration(|configuration| {
             let mut is_changed = false;
             if !deleted_group_ids.is_empty() {
@@ -179,7 +211,6 @@ where
                     .retain(|group| !deleted_group_ids.contains(&group.id));
                 is_changed = true;
             }
-
             for group_rev in &mut all_group_revs {
                 match configuration
                     .groups
@@ -187,14 +218,20 @@ where
                     .position(|old_group_rev| old_group_rev.id == group_rev.id)
                 {
                     None => {
+                        // Push the group to the end of the list if it doesn't exist in the group
                         configuration.groups.push(group_rev.clone());
                         is_changed = true;
                     }
                     Some(pos) => {
                         let mut old_group = configuration.groups.remove(pos);
+
+                        // Take the old group setting
                         group_rev.update_with_other(&old_group);
-                        is_changed = is_group_changed(group_rev, &old_group);
+                        if !is_changed {
+                            is_changed = is_group_changed(group_rev, &old_group);
+                        }
 
+                        // Consider the the name of the `group_rev` as the newest.
                         old_group.name = group_rev.name.clone();
                         configuration.groups.insert(pos, old_group);
                     }
@@ -203,6 +240,7 @@ where
             is_changed
         })?;
 
+        // Update the memory cache of the groups
         all_group_revs.into_iter().for_each(|group_rev| {
             let filter_content = filter_content_map
                 .get(&group_rev.id)
@@ -257,24 +295,6 @@ where
         Ok(())
     }
 
-    #[tracing::instrument(level = "trace", skip_all, err)]
-    pub fn save_configuration(&self) -> FlowyResult<()> {
-        let configuration = (&*self.configuration).clone();
-        let writer = self.writer.clone();
-        let field_id = self.field_rev.id.clone();
-        let field_type = self.field_rev.ty;
-        tokio::spawn(async move {
-            match writer.save_configuration(&field_id, field_type, configuration).await {
-                Ok(_) => {}
-                Err(e) => {
-                    tracing::error!("Save group configuration failed: {}", e);
-                }
-            }
-        });
-
-        Ok(())
-    }
-
     fn mut_configuration(
         &mut self,
         mut_configuration_fn: impl FnOnce(&mut GroupConfigurationRevision) -> bool,
@@ -282,7 +302,18 @@ where
         let configuration = Arc::make_mut(&mut self.configuration);
         let is_changed = mut_configuration_fn(configuration);
         if is_changed {
-            let _ = self.save_configuration()?;
+            let configuration = (&*self.configuration).clone();
+            let writer = self.writer.clone();
+            let field_id = self.field_rev.id.clone();
+            let field_type = self.field_rev.ty;
+            tokio::spawn(async move {
+                match writer.save_configuration(&field_id, field_type, configuration).await {
+                    Ok(_) => {}
+                    Err(e) => {
+                        tracing::error!("Save group configuration failed: {}", e);
+                    }
+                }
+            });
         }
         Ok(())
     }
@@ -302,13 +333,6 @@ where
 
 fn merge_groups(old_groups: Vec<GroupRevision>, new_groups: Vec<GroupRevision>) -> MergeGroupResult {
     let mut merge_result = MergeGroupResult::new();
-    // if old_groups.is_empty() {
-    //     merge_result.all_group_revs.extend(new_groups.clone());
-    //     merge_result.all_group_revs.push(default_group);
-    //     merge_result.new_group_revs = new_groups;
-    //     return merge_result;
-    // }
-
     // group_map is a helper map is used to filter out the new groups.
     let mut new_group_map: IndexMap<String, GroupRevision> = IndexMap::new();
     new_groups.into_iter().for_each(|group_rev| {

+ 38 - 19
frontend/rust-lib/flowy-grid/src/services/group/controller.rs

@@ -10,14 +10,20 @@ use flowy_grid_data_model::revision::{
 use std::marker::PhantomData;
 use std::sync::Arc;
 
-// Each kind of group must implement this trait to provide custom group
-// operations. For example, insert cell data to the row_rev when creating
-// a new row.
-pub trait GroupController: GroupControllerSharedOperation + Send + Sync {
+/// The [GroupController] trait defines the group actions, including create/delete/move items
+/// For example, the group will insert a item if the one of the new [RowRevision]'s [CellRevision]s
+/// content match the group filter.
+///  
+/// Different [FieldType] has a different controller that implements the [GroupController] trait.
+/// If the [FieldType] doesn't implement its group controller, then the [DefaultGroupController] will
+/// be used.
+///
+pub trait GroupController: GroupControllerActions + Send + Sync {
     fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
     fn did_create_row(&mut self, row_pb: &RowPB, group_id: &str);
 }
 
+/// The [GroupGenerator] trait is used to generate the groups for different [FieldType]
 pub trait GroupGenerator {
     type Context;
     type TypeOptionType;
@@ -26,10 +32,10 @@ pub trait GroupGenerator {
         field_id: &str,
         group_ctx: &Self::Context,
         type_option: &Option<Self::TypeOptionType>,
-    ) -> Vec<GeneratedGroup>;
+    ) -> Vec<GeneratedGroupConfig>;
 }
 
-pub struct GeneratedGroup {
+pub struct GeneratedGroupConfig {
     pub group_rev: GroupRevision,
     pub filter_content: String,
 }
@@ -42,29 +48,42 @@ pub struct MoveGroupRowContext<'a> {
     pub to_row_id: Option<String>,
 }
 
-// Defines the shared actions each group controller can perform.
-pub trait GroupControllerSharedOperation: Send + Sync {
-    // The field that is used for grouping the rows
+/// Defines the shared actions each group controller can perform.
+pub trait GroupControllerActions: Send + Sync {
+    /// The field that is used for grouping the rows
     fn field_id(&self) -> &str;
+
+    /// Returns number of groups the current field has
     fn groups(&self) -> Vec<Group>;
+
+    /// Returns the index and the group data with group_id
     fn get_group(&self, group_id: &str) -> Option<(usize, Group)>;
+
+    /// Separates the rows into different groups
     fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()>;
+
+    /// Remove the group with from_group_id and insert it to the index with to_group_id
     fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()>;
-    fn did_update_row(
+
+    /// Insert the row to the group if the corresponding cell data is changed
+    fn did_update_group_row(
         &mut self,
         row_rev: &RowRevision,
         field_rev: &FieldRevision,
     ) -> FlowyResult<Vec<GroupChangesetPB>>;
 
-    fn did_delete_row(
+    /// Remove the row from the group if the corresponding cell data is changed
+    fn did_delete_delete_row(
         &mut self,
         row_rev: &RowRevision,
         field_rev: &FieldRevision,
     ) -> FlowyResult<Vec<GroupChangesetPB>>;
 
+    /// Move the row from one group to another group
     fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupChangesetPB>>;
 
-    fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>>;
+    /// Update the group if the corresponding field is changed
+    fn did_update_group_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>>;
 }
 
 /// C: represents the group configuration that impl [GroupConfigurationSerde]
@@ -106,7 +125,7 @@ where
         row_rev: &RowRevision,
         other_group_changesets: &[GroupChangesetPB],
     ) -> Option<GroupChangesetPB> {
-        let default_group = self.group_ctx.get_mut_default_group()?;
+        let default_group = self.group_ctx.get_mut_no_status_group()?;
 
         // [other_group_inserted_row] contains all the inserted rows except the default group.
         let other_group_inserted_row = other_group_changesets
@@ -167,7 +186,7 @@ where
     }
 }
 
-impl<C, T, G, P> GroupControllerSharedOperation for GenericGroupController<C, T, G, P>
+impl<C, T, G, P> GroupControllerActions for GenericGroupController<C, T, G, P>
 where
     P: CellBytesParser,
     C: GroupConfigurationContentSerde,
@@ -228,7 +247,7 @@ where
                     continue;
                 }
             }
-            match self.group_ctx.get_mut_default_group() {
+            match self.group_ctx.get_mut_no_status_group() {
                 None => {}
                 Some(default_group) => default_group.add_row(row_rev.into()),
             }
@@ -242,7 +261,7 @@ where
         self.group_ctx.move_group(from_group_id, to_group_id)
     }
 
-    fn did_update_row(
+    fn did_update_group_row(
         &mut self,
         row_rev: &RowRevision,
         field_rev: &FieldRevision,
@@ -263,7 +282,7 @@ where
         }
     }
 
-    fn did_delete_row(
+    fn did_delete_delete_row(
         &mut self,
         row_rev: &RowRevision,
         field_rev: &FieldRevision,
@@ -273,7 +292,7 @@ where
             let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
             let cell_data = cell_bytes.parser::<P>()?;
             Ok(self.remove_row_if_match(row_rev, &cell_data))
-        } else if let Some(group) = self.group_ctx.get_default_group() {
+        } else if let Some(group) = self.group_ctx.get_no_status_group() {
             Ok(vec![GroupChangesetPB::delete(
                 group.id.clone(),
                 vec![row_rev.id.clone()],
@@ -300,7 +319,7 @@ where
         }
     }
 
-    fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
+    fn did_update_group_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
         let type_option = field_rev.get_type_option::<T>(field_rev.ty);
         let groups = G::generate_groups(&field_rev.id, &self.group_ctx, &type_option);
         let changeset = self.group_ctx.init_groups(groups)?;

+ 4 - 4
frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs

@@ -7,7 +7,7 @@ use crate::services::group::controller::{
 };
 
 use crate::services::cell::insert_checkbox_cell;
-use crate::services::group::{move_group_row, GeneratedGroup};
+use crate::services::group::{move_group_row, GeneratedGroupConfig};
 use flowy_grid_data_model::revision::{
     CellRevision, CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision,
 };
@@ -116,13 +116,13 @@ impl GroupGenerator for CheckboxGroupGenerator {
         _field_id: &str,
         _group_ctx: &Self::Context,
         _type_option: &Option<Self::TypeOptionType>,
-    ) -> Vec<GeneratedGroup> {
-        let check_group = GeneratedGroup {
+    ) -> Vec<GeneratedGroupConfig> {
+        let check_group = GeneratedGroupConfig {
             group_rev: GroupRevision::new(CHECK.to_string(), "".to_string()),
             filter_content: CHECK.to_string(),
         };
 
-        let uncheck_group = GeneratedGroup {
+        let uncheck_group = GeneratedGroupConfig {
             group_rev: GroupRevision::new(UNCHECK.to_string(), "".to_string()),
             filter_content: UNCHECK.to_string(),
         };

+ 9 - 5
frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs

@@ -1,9 +1,13 @@
 use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
-use crate::services::group::{Group, GroupController, GroupControllerSharedOperation, MoveGroupRowContext};
+use crate::services::group::{Group, GroupController, GroupControllerActions, MoveGroupRowContext};
 use flowy_error::FlowyResult;
 use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
 use std::sync::Arc;
 
+/// A [DefaultGroupController] is used to handle the group actions for the [FieldType] that doesn't
+/// implement its own group controller. The default group controller only contains one group, which
+/// means all rows will be grouped in the same group.
+///
 pub struct DefaultGroupController {
     pub field_id: String,
     pub group: Group,
@@ -26,7 +30,7 @@ impl DefaultGroupController {
     }
 }
 
-impl GroupControllerSharedOperation for DefaultGroupController {
+impl GroupControllerActions for DefaultGroupController {
     fn field_id(&self) -> &str {
         &self.field_id
     }
@@ -50,7 +54,7 @@ impl GroupControllerSharedOperation for DefaultGroupController {
         Ok(())
     }
 
-    fn did_update_row(
+    fn did_update_group_row(
         &mut self,
         _row_rev: &RowRevision,
         _field_rev: &FieldRevision,
@@ -58,7 +62,7 @@ impl GroupControllerSharedOperation for DefaultGroupController {
         Ok(vec![])
     }
 
-    fn did_delete_row(
+    fn did_delete_delete_row(
         &mut self,
         _row_rev: &RowRevision,
         _field_rev: &FieldRevision,
@@ -70,7 +74,7 @@ impl GroupControllerSharedOperation for DefaultGroupController {
         todo!()
     }
 
-    fn did_update_field(&mut self, _field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
+    fn did_update_group_field(&mut self, _field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
         Ok(None)
     }
 }

+ 2 - 2
frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs

@@ -8,7 +8,7 @@ use crate::services::group::controller::{
 };
 use crate::services::group::controller_impls::select_option_controller::util::*;
 
-use crate::services::group::GeneratedGroup;
+use crate::services::group::GeneratedGroupConfig;
 use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
 
 // MultiSelect
@@ -83,7 +83,7 @@ impl GroupGenerator for MultiSelectGroupGenerator {
         field_id: &str,
         group_ctx: &Self::Context,
         type_option: &Option<Self::TypeOptionType>,
-    ) -> Vec<GeneratedGroup> {
+    ) -> Vec<GeneratedGroupConfig> {
         match type_option {
             None => vec![],
             Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),

+ 2 - 2
frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs

@@ -9,7 +9,7 @@ use crate::services::group::controller::{
 use crate::services::group::controller_impls::select_option_controller::util::*;
 use crate::services::group::entities::Group;
 
-use crate::services::group::GeneratedGroup;
+use crate::services::group::GeneratedGroupConfig;
 use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
 
 // SingleSelect
@@ -83,7 +83,7 @@ impl GroupGenerator for SingleSelectGroupGenerator {
         field_id: &str,
         group_ctx: &Self::Context,
         type_option: &Option<Self::TypeOptionType>,
-    ) -> Vec<GeneratedGroup> {
+    ) -> Vec<GeneratedGroupConfig> {
         match type_option {
             None => vec![],
             Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),

+ 3 - 3
frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs

@@ -3,7 +3,7 @@ use crate::services::cell::{insert_checkbox_cell, insert_select_option_cell};
 use crate::services::field::{SelectOptionCellDataPB, SelectOptionPB, CHECK};
 use crate::services::group::configuration::GroupContext;
 use crate::services::group::controller::MoveGroupRowContext;
-use crate::services::group::{GeneratedGroup, Group};
+use crate::services::group::{GeneratedGroupConfig, Group};
 use flowy_grid_data_model::revision::{
     CellRevision, FieldRevision, GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision,
 };
@@ -155,10 +155,10 @@ pub fn generate_select_option_groups(
     _field_id: &str,
     _group_ctx: &SelectOptionGroupContext,
     options: &[SelectOptionPB],
-) -> Vec<GeneratedGroup> {
+) -> Vec<GeneratedGroupConfig> {
     let groups = options
         .iter()
-        .map(|option| GeneratedGroup {
+        .map(|option| GeneratedGroupConfig {
             group_rev: GroupRevision::new(option.id.clone(), option.name.clone()),
             filter_content: option.id.clone(),
         })

+ 21 - 3
frontend/rust-lib/flowy-grid/src/services/group/group_util.rs

@@ -13,6 +13,17 @@ use flowy_grid_data_model::revision::{
 };
 use std::sync::Arc;
 
+/// Returns a group controller.
+///
+/// Each view can be grouped by one field, each field has its own group controller.  
+/// # Arguments
+///
+/// * `view_id`: the id of the view
+/// * `field_rev`: the grouping field
+/// * `row_revs`: the rows will be separated into different groups
+/// * `configuration_reader`: a reader used to read the group configuration from disk
+/// * `configuration_writer`: as writer used to write the group configuration to disk
+///
 #[tracing::instrument(level = "trace", skip_all, err)]
 pub async fn make_group_controller<R, W>(
     view_id: String,
@@ -58,6 +69,7 @@ where
         }
     }
 
+    // Separates the rows into different groups
     let _ = group_controller.fill_groups(&row_revs, &field_rev)?;
     Ok(group_controller)
 }
@@ -75,6 +87,12 @@ pub fn find_group_field(field_revs: &[Arc<FieldRevision>], layout: &LayoutRevisi
     }
 }
 
+/// Returns a `default` group configuration for the [FieldRevision]
+///
+/// # Arguments
+///
+/// * `field_rev`: making the group configuration for the field
+///
 pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision {
     let field_id = field_rev.id.clone();
     let field_type_rev = field_rev.ty;
@@ -115,17 +133,17 @@ pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurat
     };
 
     // Append the no `status` group
-    let default_group_rev = GroupRevision {
+    let no_status_group_rev = GroupRevision {
         id: field_rev.id.clone(),
         name: format!("No {}", field_rev.name),
         visible: true,
     };
 
-    group_configuration_rev.groups.push(default_group_rev);
+    group_configuration_rev.groups.push(no_status_group_rev);
     group_configuration_rev
 }
 
-pub fn make_default_group(field_rev: &FieldRevision) -> GroupRevision {
+pub fn make_no_status_group(field_rev: &FieldRevision) -> GroupRevision {
     GroupRevision {
         id: field_rev.id.clone(),
         name: format!("No {}", field_rev.name),

+ 12 - 2
shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs

@@ -133,11 +133,20 @@ impl GridRevisionPad {
         )
     }
 
+    /// Modifies the current field type of the [FieldTypeRevision]
+    ///
+    /// # Arguments
+    ///
+    /// * `field_id`: the id of the field
+    /// * `field_type`: the new field type of the field
+    /// * `type_option_builder`: builder for creating the field type's type option data
+    ///
+    ///
     pub fn switch_to_field<B, T>(
         &mut self,
         field_id: &str,
         field_type: T,
-        type_option_json_builder: B,
+        type_option_builder: B,
     ) -> CollaborateResult<Option<GridRevisionChangeset>>
     where
         B: FnOnce(&FieldTypeRevision) -> String,
@@ -153,8 +162,9 @@ impl GridRevisionPad {
                 }
                 Some(field_rev) => {
                     let mut_field_rev = Arc::make_mut(field_rev);
+                    // If the type option data isn't exist before, creating the default type option data.
                     if mut_field_rev.get_type_option_str(field_type).is_none() {
-                        let type_option_json = type_option_json_builder(&field_type);
+                        let type_option_json = type_option_builder(&field_type);
                         mut_field_rev.insert_type_option_str(&field_type, type_option_json);
                     }