Procházet zdrojové kódy

Merge branch 'main' of github.com:AppFlowy-IO/AppFlowy

Sean Riley Hawkins před 2 roky
rodič
revize
5139518355

+ 7 - 15
.githooks/pre-push

@@ -24,21 +24,13 @@ if [[ `git status --porcelain` ]]; then
   exit 1
 fi
 
-printMessage "Running the Flutter analyzer"
-flutter analyze
-
-if [ $? -ne 0 ]; then
-  printError "Flutter analyzer error"
-  exit 1
-fi
-
-printMessage "Finished running the Flutter analyzer"
-
-
-#printMessage "Running unit tests"
-#flutter test
+#
+#printMessage "Running the Flutter analyzer"
+#flutter analyze
+#
 #if [ $? -ne 0 ]; then
-#  printf "\e[31;1m%s\e[0m\n" 'Unit tests error'
+#  printError "Flutter analyzer error"
 #  exit 1
 #fi
-#printf "\e[33;1m%s\e[0m\n" 'Finished running unit tests'
+#
+#printMessage "Finished running the Flutter analyzer"

+ 1 - 1
README.md

@@ -38,7 +38,7 @@ Please view the [documentation](https://appflowy.gitbook.io/docs/essential-docum
 
 ## Stay Up-to-Date
 
-<p align="center"><img src="https://github.com/AppFlowy-IO/appflowy/blob/main/doc/imgs/howtostar.gif" alt="AppFlowy Github" width="1000px" /></p>
+<p align="center"><img src="https://github.com/AppFlowy-IO/appflowy/blob/main/doc/imgs/howtostar.gif" alt="AppFlowy Github - how to star the repo" width="100%" /></p>
 
 ## Getting Started with development
 Please view the [documentation](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy) for OS specific development instructions

+ 3 - 1
doc/roadmap.md

@@ -1 +1,3 @@
-https://trello.com/b/NCyXCXXh/appflowy-roadmap
+[AppFlowy Roadmap ReadMe](https://appflowy.gitbook.io/docs/essential-documentation/roadmap)
+
+[AppFlowy Public Roadmap](https://github.com/orgs/AppFlowy-IO/projects/5/views/12)

+ 2 - 1
frontend/app_flowy/.gitignore

@@ -64,4 +64,5 @@ windows/flutter/dart_ffi/
 **/**/*.dll
 **/**/*.so
 **/**/Brewfile.lock.json
-**/.sandbox
+**/.sandbox
+**/.vscode/

+ 27 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart

@@ -1,9 +1,11 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/grid_bloc.dart';
 import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
+import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -250,6 +252,8 @@ class _GridFooter extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    final rowCount = context.watch<GridBloc>().state.rowInfos.length;
+    final theme = context.watch<AppTheme>();
     return SliverPadding(
       padding: const EdgeInsets.only(bottom: 200),
       sliver: SliverToBoxAdapter(
@@ -260,7 +264,14 @@ class _GridFooter extends StatelessWidget {
             child: Row(
               children: [
                 SizedBox(width: GridSize.leadingHeaderPadding),
-                const SizedBox(width: 120, child: GridAddRowButton()),
+                Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children:  [
+                    const SizedBox(width: 120, child: GridAddRowButton()),
+                    const SizedBox(height: 30),
+                    _rowCountTextWidget(theme: theme,count: rowCount)
+                  ],
+                ),
               ],
             ),
           ),
@@ -268,4 +279,19 @@ class _GridFooter extends StatelessWidget {
       ),
     );
   }
+
+  Widget _rowCountTextWidget({required AppTheme theme, required int count}){
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.start,
+      children: [
+        FlowyText.regular('Count : ',
+         fontSize: 13,
+         color: theme.shader3,
+        ),
+        FlowyText.regular(count.toString(),
+         fontSize: 13,
+        ),
+      ],
+    );
+  }
 }

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart

@@ -5,7 +5,7 @@ class GridSize {
 
   static double get scrollBarSize => 12 * scale;
   static double get headerHeight => 40 * scale;
-  static double get footerHeight => 40 * scale;
+  static double get footerHeight => 100 * scale;
   static double get leadingHeaderPadding => 50 * scale;
   static double get trailHeaderPadding => 140 * scale;
   static double get headerContainerPadding => 0 * scale;

+ 15 - 13
frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart

@@ -41,20 +41,22 @@ class ListOverlay extends StatelessWidget {
     return OverlayContainer(
       constraints: BoxConstraints.tight(Size(width, totalHeight)),
       padding: padding,
-      child: Column(
-        children: [
-          ListView.builder(
-            shrinkWrap: true,
-            itemBuilder: itemBuilder,
-            itemCount: itemCount,
-            controller: controller,
-          ),
-          if (footer != null)
-            Padding(
-              padding: footer!.padding,
-              child: footer!.widget,
+      child: SingleChildScrollView(
+        child: Column(
+          children: [
+            ListView.builder(
+              shrinkWrap: true,
+              itemBuilder: itemBuilder,
+              itemCount: itemCount,
+              controller: controller,
             ),
-        ],
+            if (footer != null)
+              Padding(
+                padding: footer!.padding,
+                child: footer!.widget,
+              ),
+          ],
+        ),
       ),
     );
   }

+ 1 - 1
frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart

@@ -18,7 +18,7 @@ class OverlayContainer extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
+    final theme = context.watch<AppTheme?>() ?? AppTheme.fromType(ThemeType.light);
     return Material(
       type: MaterialType.transparency,
       child: Container(

+ 12 - 0
frontend/rust-lib/flowy-grid/src/entities/block_entities.rs

@@ -4,6 +4,13 @@ use flowy_grid_data_model::parser::NotEmptyStr;
 use flowy_grid_data_model::revision::RowRevision;
 use std::sync::Arc;
 
+/// [GridBlockPB] contains list of row ids. The rows here does not contain any data, just the id
+/// of the row. Check out [GridRowPB] for more details.
+///
+///
+/// A grid can have many rows. Rows are therefore grouped into Blocks in order to make
+/// things more efficient.
+///                                        |
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct GridBlockPB {
     #[pb(index = 1)]
@@ -22,6 +29,7 @@ impl GridBlockPB {
     }
 }
 
+/// [GridRowPB] Describes a row. Has the id of the parent Block. Has the metadata of the row.
 #[derive(Debug, Default, Clone, ProtoBuf)]
 pub struct GridRowPB {
     #[pb(index = 1)]
@@ -81,6 +89,8 @@ impl std::convert::From<Vec<GridRowPB>> for RepeatedRowPB {
         Self { items }
     }
 }
+
+/// [RepeatedGridBlockPB] contains list of [GridBlockPB]
 #[derive(Debug, Default, ProtoBuf)]
 pub struct RepeatedGridBlockPB {
     #[pb(index = 1)]
@@ -194,6 +204,8 @@ impl GridBlockChangesetPB {
     }
 }
 
+/// [QueryGridBlocksPayloadPB] is used to query the data of the block that belongs to the grid whose
+/// id is grid_id.
 #[derive(ProtoBuf, Default)]
 pub struct QueryGridBlocksPayloadPB {
     #[pb(index = 1)]

+ 1 - 0
frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs

@@ -119,6 +119,7 @@ impl std::convert::From<Vec<GridCellPB>> for RepeatedCellPB {
     }
 }
 
+///
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct CellChangesetPB {
     #[pb(index = 1)]

+ 19 - 0
frontend/rust-lib/flowy-grid/src/entities/field_entities.rs

@@ -8,6 +8,7 @@ use std::sync::Arc;
 
 use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString};
 
+/// [GridFieldPB] defines a Field's attributes. Such as the name, field_type, and width. etc.
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct GridFieldPB {
     #[pb(index = 1)]
@@ -56,6 +57,8 @@ impl std::convert::From<Arc<FieldRevision>> for GridFieldPB {
         GridFieldPB::from(field_rev)
     }
 }
+
+/// [GridFieldIdPB] id of the [Field]
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct GridFieldIdPB {
     #[pb(index = 1)]
@@ -257,6 +260,13 @@ impl TryInto<GridFieldTypeOptionIdParams> for GridFieldTypeOptionIdPB {
     }
 }
 
+/// 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)]
@@ -269,6 +279,7 @@ pub struct FieldTypeOptionDataPB {
     pub type_option_data: Vec<u8>,
 }
 
+/// Collection of the [GridFieldPB]
 #[derive(Debug, Default, ProtoBuf)]
 pub struct RepeatedGridFieldPB {
     #[pb(index = 1)]
@@ -364,6 +375,7 @@ impl TryInto<InsertFieldParams> for InsertFieldPayloadPB {
     }
 }
 
+/// [UpdateFieldTypeOptionPayloadPB] is used to update the type option data.
 #[derive(ProtoBuf, Default)]
 pub struct UpdateFieldTypeOptionPayloadPB {
     #[pb(index = 1)]
@@ -372,6 +384,7 @@ pub struct UpdateFieldTypeOptionPayloadPB {
     #[pb(index = 2)]
     pub field_id: String,
 
+    /// Check out [FieldTypeOptionDataPB] for more details.
     #[pb(index = 3)]
     pub type_option_data: Vec<u8>,
 }
@@ -424,6 +437,12 @@ impl TryInto<QueryFieldParams> for QueryFieldPayloadPB {
     }
 }
 
+/// [FieldChangesetPayloadPB] is used to modify the corresponding field. It defines which properties of
+/// the field can be modified.
+///
+/// Pass in None if you don't want to modify a property
+/// Pass in Some(Value) if you want to modify a property
+///
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct FieldChangesetPayloadPB {
     #[pb(index = 1)]

+ 2 - 0
frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs

@@ -2,6 +2,8 @@ use crate::entities::{GridBlockPB, GridFieldIdPB};
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
+
+/// [GridPB] describes how many fields and blocks the grid has
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct GridPB {
     #[pb(index = 1)]

+ 1 - 0
frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs

@@ -12,6 +12,7 @@ use std::convert::TryInto;
 use strum::IntoEnumIterator;
 use strum_macros::EnumIter;
 
+/// [GridSettingPB] defines the setting options for the grid. Such as the filter, group, and sort.
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
 pub struct GridSettingPB {
     #[pb(index = 1)]

+ 85 - 0
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -42,63 +42,132 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
     module
 }
 
+/// [GridEvent] defines events that are used to interact with the Grid. You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/backend/protobuf)
+/// out, it includes how to use these annotations: input, output, etc.
 #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
 #[event_err = "FlowyError"]
 pub enum GridEvent {
+    /// [GetGrid] event is used to get the [GridPB]
+    ///
+    /// The event handler accepts a [GridIdPB] and returns a [GridPB] if there are no errors.
     #[event(input = "GridIdPB", output = "GridPB")]
     GetGrid = 0,
 
+    /// [GetGridBlocks] event is used to get the grid's block.
+    ///
+    /// The event handler accepts a [QueryGridBlocksPayloadPB] and returns a [RepeatedGridBlockPB]
+    /// if there are no errors.
     #[event(input = "QueryGridBlocksPayloadPB", output = "RepeatedGridBlockPB")]
     GetGridBlocks = 1,
 
+    /// [GetGridSetting] event is used to get the grid's settings.
+    ///
+    /// The event handler accepts [GridIdPB] and return [GridSettingPB]
+    /// if there is no errors.
     #[event(input = "GridIdPB", output = "GridSettingPB")]
     GetGridSetting = 2,
 
+    /// [UpdateGridSetting] event is used to update the grid's settings.
+    ///
+    /// The event handler accepts [GridIdPB] and return errors if failed to modify the grid's settings.
     #[event(input = "GridIdPB", input = "GridSettingChangesetPayloadPB")]
     UpdateGridSetting = 3,
 
+    /// [GetFields] event is used to get the grid's settings.
+    ///
+    /// The event handler accepts a [QueryFieldPayloadPB] and returns a [RepeatedGridFieldPB]
+    /// if there are no errors.
     #[event(input = "QueryFieldPayloadPB", output = "RepeatedGridFieldPB")]
     GetFields = 10,
 
+    /// [UpdateField] event is used to update a field's attributes.
+    ///
+    /// The event handler accepts a [FieldChangesetPayloadPB] and returns errors if failed to modify the
+    /// field.
     #[event(input = "FieldChangesetPayloadPB")]
     UpdateField = 11,
 
+    /// [UpdateFieldTypeOption] event is used to update the field's type option data. 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.
+    ///
+    /// Check out [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
+    /// for more information.
+    ///
+    /// The event handler accepts a [UpdateFieldTypeOptionPayloadPB] and returns errors if failed to modify the
+    /// field.
     #[event(input = "UpdateFieldTypeOptionPayloadPB")]
     UpdateFieldTypeOption = 12,
 
+    /// [InsertField] event is used to insert a new Field. If the Field already exists, the event
+    /// handler will replace the value with the new Field value.
     #[event(input = "InsertFieldPayloadPB")]
     InsertField = 13,
 
+    /// [DeleteField] event is used to delete a Field. [DeleteFieldPayloadPB] is the context that
+    /// is used to delete the field from the Grid.
     #[event(input = "DeleteFieldPayloadPB")]
     DeleteField = 14,
 
+    /// [SwitchToField] event is used to update the current Field's type.
+    /// It will insert a new FieldTypeOptionData if the new FieldType doesn't exist before, otherwise
+    /// reuse the existing FieldTypeOptionData. You could check the [GridRevisionPad] for more details.
     #[event(input = "EditFieldPayloadPB", output = "FieldTypeOptionDataPB")]
     SwitchToField = 20,
 
+    /// [DuplicateField] event is used to duplicate a Field. The duplicated field data is kind of
+    /// deep copy of the target field. The passed in [DuplicateFieldPayloadPB] is the context that is
+    /// used to duplicate the field.
+    ///
+    /// Return errors if failed to duplicate the field.
+    ///
     #[event(input = "DuplicateFieldPayloadPB")]
     DuplicateField = 21,
 
+    /// [MoveItem] event is used to move an item. For the moment, Item has two types defined in
+    /// [MoveItemTypePB].
     #[event(input = "MoveItemPayloadPB")]
     MoveItem = 22,
 
+    /// [GetFieldTypeOption] event is used to get the FieldTypeOption data for a specific field type.
+    ///
+    /// Check out the [FieldTypeOptionDataPB] for more details. If the [FieldTypeOptionData] does exist
+    /// for the target type, the [TypeOptionBuilder] will create the default data for that type.
+    ///
+    /// Return the [FieldTypeOptionDataPB] if there are no errors.
     #[event(input = "GridFieldTypeOptionIdPB", output = "FieldTypeOptionDataPB")]
     GetFieldTypeOption = 23,
 
+    /// [CreateFieldTypeOption] event is used to create a new FieldTypeOptionData.
     #[event(input = "CreateFieldPayloadPB", output = "FieldTypeOptionDataPB")]
     CreateFieldTypeOption = 24,
 
+    /// [NewSelectOption] event is used to create a new select option. Returns a [SelectOptionPB] if
+    /// there are no errors.
     #[event(input = "CreateSelectOptionPayloadPB", output = "SelectOptionPB")]
     NewSelectOption = 30,
 
+    /// [GetSelectOptionCellData] event is used to get the select option data for cell editing.
+    /// [GridCellIdPB] locate which cell data that will be read from. The return value, [SelectOptionCellDataPB]
+    /// contains the available options and the currently selected options.
     #[event(input = "GridCellIdPB", output = "SelectOptionCellDataPB")]
     GetSelectOptionCellData = 31,
 
+    /// [UpdateSelectOption] event is used to update a FieldTypeOptionData whose field_type is
+    /// FieldType::SingleSelect or FieldType::MultiSelect.
+    ///
+    /// This event may trigger the GridNotification::DidUpdateCell event.
+    /// For example, GridNotification::DidUpdateCell will be triggered if the [SelectOptionChangesetPayloadPB]
+    /// carries a change that updates the name of the option.
     #[event(input = "SelectOptionChangesetPayloadPB")]
     UpdateSelectOption = 32,
 
     #[event(input = "CreateRowPayloadPB", output = "GridRowPB")]
     CreateRow = 50,
 
+    /// [GetRow] event is used to get the row data,[GridRowPB]. [OptionalRowPB] is a wrapper that enables
+    /// to return a nullable row data.
     #[event(input = "GridRowIdPB", output = "OptionalRowPB")]
     GetRow = 51,
 
@@ -111,12 +180,28 @@ pub enum GridEvent {
     #[event(input = "GridCellIdPB", output = "GridCellPB")]
     GetCell = 70,
 
+    /// [UpdateCell] event is used to update the cell content. The passed in data, [CellChangesetPB],
+    /// carries the changes that will be applied to the cell content by calling `update_cell` function.
+    ///
+    /// The 'content' property of the [CellChangesetPB] is a String type. It can be used directly if the
+    /// cell uses string data. For example, the TextCell or NumberCell.
+    ///
+    /// But,it can be treated as a generic type, because we can use [serde] to deserialize the string
+    /// into a specific data type. For the moment, the 'content' will be deserialized to a concrete type
+    /// when the FieldType is SingleSelect, DateTime, and MultiSelect. Please see
+    /// the [UpdateSelectOptionCell] and [UpdateDateCell] events for more details.
     #[event(input = "CellChangesetPB")]
     UpdateCell = 71,
 
+    /// [UpdateSelectOptionCell] event is used to update a select option cell's data. [SelectOptionCellChangesetPayloadPB]
+    /// contains options that will be deleted or inserted. It can be cast to [CellChangesetPB] that
+    /// will be used by the `update_cell` function.
     #[event(input = "SelectOptionCellChangesetPayloadPB")]
     UpdateSelectOptionCell = 72,
 
+    /// [UpdateDateCell] event is used to update a date cell's data. [DateChangesetPayloadPB]
+    /// contains the date and the time string. It can be cast to [CellChangesetPB] that
+    /// will be used by the `update_cell` function.
     #[event(input = "DateChangesetPayloadPB")]
     UpdateDateCell = 80,
 }

+ 7 - 0
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs

@@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize};
 
 pub const SELECTION_IDS_SEPARATOR: &str = ",";
 
+/// [SelectOptionPB] represents an option for a single select, and multiple select.
 #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, ProtoBuf)]
 pub struct SelectOptionPB {
     #[pb(index = 1)]
@@ -322,15 +323,21 @@ impl SelectOptionCellChangeset {
     }
 }
 
+/// [SelectOptionCellDataPB] contains a list of user's selected options and a list of all the options
+/// that the cell can use.
 #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
 pub struct SelectOptionCellDataPB {
+    /// The available options that the cell can use.
     #[pb(index = 1)]
     pub options: Vec<SelectOptionPB>,
 
+    /// The selected options for the cell.
     #[pb(index = 2)]
     pub select_options: Vec<SelectOptionPB>,
 }
 
+/// [SelectOptionChangesetPayloadPB] describes the changes of a FieldTypeOptionData. For the moment,
+/// it is used by [MultiSelectTypeOptionPB] and [SingleSelectTypeOptionPB].
 #[derive(Clone, Debug, Default, ProtoBuf)]
 pub struct SelectOptionChangesetPayloadPB {
     #[pb(index = 1)]

+ 0 - 1
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -103,7 +103,6 @@ impl GridRevisionEditor {
                 .modify(|grid| {
                     let builder = type_option_builder_from_bytes(type_option_data, &field.field_type);
                     let field_rev = FieldBuilder::from_field(field, builder).build();
-
                     Ok(grid.create_field_rev(field_rev, start_field_id)?)
                 })
                 .await?;

+ 1 - 1
frontend/scripts/docker-buildfiles/Dockerfile

@@ -33,7 +33,7 @@ source $HOME/.cargo/env && \
 cargo install --force cargo-make && \
 cargo install --force duckscript_cli && \
 cargo make flowy_dev && \
-cargo make -p production-linux-x86 appflowy-linux
+cargo make -p production-linux-x86_64 appflowy-linux
 
 CMD ["/home/makepkg/appflowy/frontend/app_flowy/build/linux/x64/release/bundle/app_flowy"]
 

+ 1 - 1
frontend/scripts/install_dev_env/install_macos.sh

@@ -53,7 +53,7 @@ git config core.hooksPath .githooks
 # Install go-gitlint 
 printMessage "Installing go-gitlint."
 GOLINT_FILENAME="go-gitlint_1.1.0_osx_x86_64.tar.gz"
-wget https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME}
+curl -L https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME} --output ${GOLINT_FILENAME}
 tar -zxv --directory .githooks/. -f ${GOLINT_FILENAME} gitlint 
 rm ${GOLINT_FILENAME}
 

+ 6 - 0
shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs

@@ -123,6 +123,7 @@ pub struct FieldRevision {
     /// type_options contains key/value pairs
     /// key: id of the FieldType
     /// value: type option data that can be parsed into specified TypeOptionStruct.
+    ///
     /// For example, CheckboxTypeOption, MultiSelectTypeOption etc.
     #[serde(with = "indexmap::serde_seq")]
     pub type_options: IndexMap<String, String>,
@@ -185,15 +186,20 @@ impl FieldRevision {
     }
 }
 
+/// The macro [impl_type_option] will implement the [TypeOptionDataEntry] for the type that
+/// supports the serde trait and the TryInto<Bytes> trait.
 pub trait TypeOptionDataEntry {
     fn json_str(&self) -> String;
     fn protobuf_bytes(&self) -> Bytes;
 }
 
+/// The macro [impl_type_option] will implement the [TypeOptionDataDeserializer] for the type that
+/// supports the serde trait and the TryFrom<Bytes> trait.
 pub trait TypeOptionDataDeserializer {
     fn from_json_str(s: &str) -> Self;
     fn from_protobuf_bytes(bytes: Bytes) -> Self;
 }
+
 pub type FieldId = String;
 #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
 pub struct RowRevision {