瀏覽代碼

chore: config sort controller

nathan 2 年之前
父節點
當前提交
6b4291ccc7

+ 2 - 2
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -19,8 +19,8 @@ pub(crate) async fn get_grid_handler(
     manager: AFPluginState<Arc<GridManager>>,
 ) -> DataResult<GridPB, FlowyError> {
     let grid_id: GridIdPB = data.into_inner();
-    let editor = manager.open_grid(grid_id).await?;
-    let grid = editor.get_grid().await?;
+    let editor = manager.open_grid(grid_id.as_ref()).await?;
+    let grid = editor.get_grid(grid_id.as_ref()).await?;
     data_result(grid)
 }
 

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

@@ -228,6 +228,7 @@ impl GridBlockManager {
         editor.get_row_rev(row_id).await
     }
 
+    #[allow(dead_code)]
     pub async fn get_row_revs(&self, block_id: &str) -> FlowyResult<Vec<Arc<RowRevision>>> {
         let editor = self.get_block_editor(block_id).await?;
         editor.get_row_revs::<&str>(None).await

+ 1 - 1
frontend/rust-lib/flowy-grid/src/services/filter/controller.rs

@@ -44,7 +44,7 @@ impl FilterController {
         notifier: GridViewChangedNotifier,
     ) -> Self
     where
-        T: FilterDelegate,
+        T: FilterDelegate + 'static,
     {
         let mut this = Self {
             view_id: view_id.to_string(),

+ 3 - 4
frontend/rust-lib/flowy-grid/src/services/filter/entities.rs

@@ -71,12 +71,11 @@ pub struct FilterType {
     pub field_type: FieldType,
 }
 
-impl FilterType {
-    pub fn field_type_rev(&self) -> FieldTypeRevision {
-        self.field_type.clone().into()
+impl Into<FieldTypeRevision> for FilterType {
+    fn into(self) -> FieldTypeRevision {
+        self.field_type.into()
     }
 }
-
 impl std::convert::From<&Arc<FieldRevision>> for FilterType {
     fn from(rev: &Arc<FieldRevision>) -> Self {
         Self {

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

@@ -394,11 +394,11 @@ impl GridRevisionEditor {
     }
 
     /// Returns all the rows in this block.
-    pub async fn get_row_pbs(&self, block_id: &str) -> FlowyResult<Vec<RowPB>> {
-        let rows = self.block_manager.get_row_revs(block_id).await?;
+    pub async fn get_row_pbs(&self, view_id: &str, block_id: &str) -> FlowyResult<Vec<RowPB>> {
+        let rows = self.view_manager.get_row_revs(view_id, block_id).await?;
         let rows = self
             .view_manager
-            .filter_rows(block_id, rows)
+            .filter_rows(view_id, block_id, rows)
             .await?
             .into_iter()
             .map(|row_rev| RowPB::from(&row_rev))
@@ -535,12 +535,12 @@ impl GridRevisionEditor {
         Ok(())
     }
 
-    pub async fn get_grid(&self) -> FlowyResult<GridPB> {
+    pub async fn get_grid(&self, view_id: &str) -> FlowyResult<GridPB> {
         let pad = self.grid_pad.read().await;
         let fields = pad.get_field_revs(None)?.iter().map(FieldIdPB::from).collect();
         let mut all_rows = vec![];
         for block_rev in pad.get_block_meta_revs() {
-            if let Ok(rows) = self.get_row_pbs(&block_rev.block_id).await {
+            if let Ok(rows) = self.get_row_pbs(view_id, &block_rev.block_id).await {
                 all_rows.extend(rows);
             }
         }

+ 2 - 2
frontend/rust-lib/flowy-grid/src/services/grid_editor_trait_impl.rs

@@ -51,11 +51,11 @@ impl GridViewEditorDelegate for GridViewEditorDelegateImpl {
         })
     }
 
-    fn get_row_revs(&self) -> Fut<Vec<Arc<RowRevision>>> {
+    fn get_row_revs(&self, block_id: Option<Vec<String>>) -> Fut<Vec<Arc<RowRevision>>> {
         let block_manager = self.block_manager.clone();
 
         to_fut(async move {
-            let blocks = block_manager.get_blocks(None).await.unwrap();
+            let blocks = block_manager.get_blocks(block_id).await.unwrap();
             blocks
                 .into_iter()
                 .flat_map(|block| block.row_revs)

+ 42 - 3
frontend/rust-lib/flowy-grid/src/services/sort/controller.rs

@@ -1,6 +1,45 @@
-pub struct SortController {}
+use crate::services::sort::SortType;
+use flowy_task::TaskDispatcher;
+use grid_rev_model::{FieldRevision, RowRevision, SortRevision};
+use lib_infra::future::Fut;
+use std::sync::Arc;
+use tokio::sync::RwLock;
+
+pub trait SortDelegate: Send + Sync {
+    fn get_sort_rev(&self, sort_type: SortType) -> Fut<Vec<Arc<SortRevision>>>;
+    fn get_field_rev(&self, field_id: &str) -> Fut<Option<Arc<FieldRevision>>>;
+    fn get_field_revs(&self, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<FieldRevision>>>;
+}
+
+pub struct SortController {
+    view_id: String,
+    handler_id: String,
+    delegate: Box<dyn SortDelegate>,
+    task_scheduler: Arc<RwLock<TaskDispatcher>>,
+}
+
 impl SortController {
-    pub fn new() -> Self {
-        Self {}
+    pub fn new<T>(view_id: &str, handler_id: &str, delegate: T, task_scheduler: Arc<RwLock<TaskDispatcher>>) -> Self
+    where
+        T: SortDelegate + 'static,
+    {
+        Self {
+            view_id: view_id.to_string(),
+            handler_id: handler_id.to_string(),
+            delegate: Box::new(delegate),
+            task_scheduler,
+        }
+    }
+
+    pub async fn close(&self) {
+        self.task_scheduler
+            .write()
+            .await
+            .unregister_handler(&self.handler_id)
+            .await;
+    }
+
+    pub fn sort_rows(&self, rows: &mut Vec<Arc<RowRevision>>) {
+        todo!()
     }
 }

+ 14 - 0
frontend/rust-lib/flowy-grid/src/services/sort/entities.rs

@@ -0,0 +1,14 @@
+use crate::entities::FieldType;
+use grid_rev_model::FieldTypeRevision;
+
+#[derive(Hash, Eq, PartialEq, Debug, Clone)]
+pub struct SortType {
+    pub field_id: String,
+    pub field_type: FieldType,
+}
+
+impl Into<FieldTypeRevision> for SortType {
+    fn into(self) -> FieldTypeRevision {
+        self.field_type.into()
+    }
+}

+ 4 - 0
frontend/rust-lib/flowy-grid/src/services/sort/mod.rs

@@ -1,3 +1,7 @@
 mod controller;
+mod entities;
+mod task;
 
 pub use controller::*;
+pub use entities::*;
+pub use task::*;

+ 29 - 0
frontend/rust-lib/flowy-grid/src/services/sort/task.rs

@@ -0,0 +1,29 @@
+use crate::services::sort::SortController;
+use flowy_task::{TaskContent, TaskHandler};
+use lib_infra::future::BoxResultFuture;
+use std::sync::Arc;
+use tokio::sync::RwLock;
+
+pub struct SortTaskHandler {
+    handler_id: String,
+    sort_controller: Arc<RwLock<SortController>>,
+}
+
+impl SortTaskHandler {
+    pub fn new(handler_id: String, sort_controller: Arc<RwLock<SortController>>) -> Self {
+        Self {
+            handler_id,
+            sort_controller,
+        }
+    }
+}
+
+impl TaskHandler for SortTaskHandler {
+    fn handler_id(&self) -> &str {
+        &self.handler_id
+    }
+
+    fn run(&self, content: TaskContent) -> BoxResultFuture<(), anyhow::Error> {
+        todo!();
+    }
+}

+ 41 - 12
frontend/rust-lib/flowy-grid/src/services/view_editor/editor.rs

@@ -7,7 +7,7 @@ use crate::services::group::{
     GroupController, MoveGroupRowContext,
 };
 use crate::services::row::GridBlockRowRevision;
-use crate::services::sort::SortController;
+use crate::services::sort::{SortController, SortTaskHandler};
 use crate::services::view_editor::changed_notifier::GridViewChangedNotifier;
 use crate::services::view_editor::trait_impl::*;
 use crate::services::view_editor::GridViewChangedReceiverRunner;
@@ -39,17 +39,22 @@ pub trait GridViewEditorDelegate: Send + Sync + 'static {
     /// Returns the index of the row with row_id
     fn index_of_row(&self, row_id: &str) -> Fut<Option<usize>>;
 
-    /// Get the row with row_id
+    /// Returns the `index` and `RowRevision` with row_id
     fn get_row_rev(&self, row_id: &str) -> Fut<Option<(usize, Arc<RowRevision>)>>;
 
-    /// Get all the rows that the current Grid has
-    /// One block has a list of rows
-    fn get_row_revs(&self) -> Fut<Vec<Arc<RowRevision>>>;
+    /// Returns all the rows that the block has. If the passed-in block_ids is None, then will return all the rows
+    /// The relationship between the grid and the block is:
+    ///     A grid has a list of blocks
+    ///     A block has a list of rows
+    ///     A row has a list of cells
+    ///
+    fn get_row_revs(&self, block_ids: Option<Vec<String>>) -> Fut<Vec<Arc<RowRevision>>>;
 
     /// Get all the blocks that the current Grid has.
     /// One grid has a list of blocks
     fn get_blocks(&self) -> Fut<Vec<GridBlockRowRevision>>;
 
+    /// Returns a `TaskDispatcher` used to poll a `Task`
     fn get_task_scheduler(&self) -> Arc<RwLock<TaskDispatcher>>;
 }
 
@@ -104,7 +109,7 @@ impl GridViewRevisionEditor {
         )
         .await?;
 
-        let sort_controller = Arc::new(RwLock::new(SortController::new()));
+        let sort_controller = make_sort_controller(&view_id, delegate.clone(), view_rev_pad.clone()).await;
 
         let user_id = user_id.to_owned();
         let group_controller = Arc::new(RwLock::new(group_controller));
@@ -159,8 +164,8 @@ impl GridViewRevisionEditor {
             .send();
     }
 
-    pub async fn notify_rows_did_changed(&self) {
-        //
+    pub async fn sort_rows(&self, rows: &mut Vec<Arc<RowRevision>>) {
+        self.sort_controller.read().await.sort_rows(rows)
     }
 
     pub async fn filter_rows(&self, _block_id: &str, mut rows: Vec<Arc<RowRevision>>) -> Vec<Arc<RowRevision>> {
@@ -420,7 +425,6 @@ impl GridViewRevisionEditor {
     #[tracing::instrument(level = "trace", skip(self), err)]
     pub async fn delete_view_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> {
         let filter_type = params.filter_type;
-        let field_type_rev = filter_type.field_type_rev();
         let changeset = self
             .filter_controller
             .write()
@@ -430,7 +434,7 @@ impl GridViewRevisionEditor {
 
         let _ = self
             .modify(|pad| {
-                let changeset = pad.delete_filter(&params.filter_id, &filter_type.field_id, &field_type_rev)?;
+                let changeset = pad.delete_filter(&params.filter_id, &filter_type.field_id, filter_type.field_type)?;
                 Ok(changeset)
             })
             .await?;
@@ -474,7 +478,7 @@ impl GridViewRevisionEditor {
     #[tracing::instrument(level = "debug", skip_all, err)]
     pub async fn group_by_view_field(&self, field_id: &str) -> FlowyResult<()> {
         if let Some(field_rev) = self.delegate.get_field_rev(field_id).await {
-            let row_revs = self.delegate.get_row_revs().await;
+            let row_revs = self.delegate.get_row_revs(None).await;
             let new_group_controller = new_group_controller_with_field_rev(
                 self.user_id.clone(),
                 self.view_id.clone(),
@@ -594,7 +598,7 @@ async fn new_group_controller(
 ) -> FlowyResult<Box<dyn GroupController>> {
     let configuration_reader = GroupConfigurationReaderImpl(view_rev_pad.clone());
     let field_revs = delegate.get_field_revs(None).await;
-    let row_revs = delegate.get_row_revs().await;
+    let row_revs = delegate.get_row_revs(None).await;
     let layout = view_rev_pad.read().await.layout();
     // Read the group field or find a new group field
     let field_rev = configuration_reader
@@ -661,6 +665,31 @@ async fn make_filter_controller(
     filter_controller
 }
 
+async fn make_sort_controller(
+    view_id: &str,
+    delegate: Arc<dyn GridViewEditorDelegate>,
+    pad: Arc<RwLock<GridViewRevisionPad>>,
+) -> Arc<RwLock<SortController>> {
+    let handler_id = gen_handler_id();
+    let sort_delegate = GridViewSortDelegateImpl {
+        editor_delegate: delegate.clone(),
+        view_revision_pad: pad,
+    };
+    let task_scheduler = delegate.get_task_scheduler();
+    let sort_controller = Arc::new(RwLock::new(SortController::new(
+        view_id,
+        &handler_id,
+        sort_delegate,
+        task_scheduler.clone(),
+    )));
+    task_scheduler
+        .write()
+        .await
+        .register_handler(SortTaskHandler::new(handler_id, sort_controller.clone()));
+
+    sort_controller
+}
+
 fn gen_handler_id() -> String {
     nanoid!(10)
 }

+ 16 - 5
frontend/rust-lib/flowy-grid/src/services/view_editor/editor_manager.rs

@@ -53,13 +53,24 @@ impl GridViewManager {
         Ok(self.get_view_editor(view_id).await?.notifier.subscribe())
     }
 
-    pub async fn get_rows(&self) -> FlowyResult<Vec<Arc<RowRevision>>> {
-        todo!()
+    pub async fn get_row_revs(&self, view_id: &str, block_id: &str) -> FlowyResult<Vec<Arc<RowRevision>>> {
+        let mut row_revs = self.delegate.get_row_revs(Some(vec![block_id.to_owned()])).await;
+        if let Ok(view_editor) = self.get_view_editor(view_id).await {
+            view_editor.sort_rows(&mut row_revs).await;
+        }
+        Ok(row_revs)
     }
 
-    pub async fn filter_rows(&self, block_id: &str, rows: Vec<Arc<RowRevision>>) -> FlowyResult<Vec<Arc<RowRevision>>> {
-        let editor = self.get_default_view_editor().await?;
-        let rows = editor.filter_rows(block_id, rows).await;
+    pub async fn filter_rows(
+        &self,
+        view_id: &str,
+        block_id: &str,
+        rows: Vec<Arc<RowRevision>>,
+    ) -> FlowyResult<Vec<Arc<RowRevision>>> {
+        let rows = match self.get_view_editor(view_id).await {
+            Ok(view_editor) => view_editor.filter_rows(block_id, rows).await,
+            Err(_) => rows,
+        };
         Ok(rows)
     }
 

+ 30 - 4
frontend/rust-lib/flowy-grid/src/services/view_editor/trait_impl.rs

@@ -2,6 +2,7 @@ use crate::entities::{GridLayout, GridLayoutPB, GridSettingPB};
 use crate::services::filter::{FilterDelegate, FilterType};
 use crate::services::group::{GroupConfigurationReader, GroupConfigurationWriter};
 use crate::services::row::GridBlockRowRevision;
+use crate::services::sort::{SortDelegate, SortType};
 use crate::services::view_editor::GridViewEditorDelegate;
 use bytes::Bytes;
 use flowy_database::ConnectionPool;
@@ -12,7 +13,9 @@ use flowy_revision::{
 };
 use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
 use flowy_sync::util::make_operations_from_revisions;
-use grid_rev_model::{FieldRevision, FieldTypeRevision, FilterRevision, GroupConfigurationRevision, RowRevision};
+use grid_rev_model::{
+    FieldRevision, FieldTypeRevision, FilterRevision, GroupConfigurationRevision, RowRevision, SortRevision,
+};
 use lib_infra::future::{to_fut, Fut, FutureResult};
 use lib_ot::core::EmptyAttributes;
 use std::sync::Arc;
@@ -132,11 +135,11 @@ pub(crate) struct GridViewFilterDelegateImpl {
 }
 
 impl FilterDelegate for GridViewFilterDelegateImpl {
-    fn get_filter_rev(&self, filter_id: FilterType) -> Fut<Option<Arc<FilterRevision>>> {
+    fn get_filter_rev(&self, filter_type: FilterType) -> Fut<Option<Arc<FilterRevision>>> {
         let pad = self.view_revision_pad.clone();
         to_fut(async move {
-            let field_type_rev: FieldTypeRevision = filter_id.field_type.into();
-            let mut filters = pad.read().await.get_filters(&filter_id.field_id, &field_type_rev);
+            let field_type_rev: FieldTypeRevision = filter_type.field_type.into();
+            let mut filters = pad.read().await.get_filters(&filter_type.field_id, &field_type_rev);
             if filters.is_empty() {
                 None
             } else {
@@ -162,3 +165,26 @@ impl FilterDelegate for GridViewFilterDelegateImpl {
         self.editor_delegate.get_row_rev(row_id)
     }
 }
+
+pub(crate) struct GridViewSortDelegateImpl {
+    pub(crate) editor_delegate: Arc<dyn GridViewEditorDelegate>,
+    pub(crate) view_revision_pad: Arc<RwLock<GridViewRevisionPad>>,
+}
+
+impl SortDelegate for GridViewSortDelegateImpl {
+    fn get_sort_rev(&self, sort_type: SortType) -> Fut<Vec<Arc<SortRevision>>> {
+        let pad = self.view_revision_pad.clone();
+        to_fut(async move {
+            let field_type_rev: FieldTypeRevision = sort_type.field_type.into();
+            pad.read().await.get_sorts(&sort_type.field_id, &field_type_rev)
+        })
+    }
+
+    fn get_field_rev(&self, field_id: &str) -> Fut<Option<Arc<FieldRevision>>> {
+        self.editor_delegate.get_field_rev(field_id)
+    }
+
+    fn get_field_revs(&self, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<FieldRevision>>> {
+        self.editor_delegate.get_field_revs(field_ids)
+    }
+}

+ 60 - 3
shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs

@@ -4,6 +4,7 @@ use flowy_http_model::revision::Revision;
 use flowy_http_model::util::md5;
 use grid_rev_model::{
     FieldRevision, FieldTypeRevision, FilterRevision, GridViewRevision, GroupConfigurationRevision, LayoutRevision,
+    SortRevision,
 };
 use lib_ot::core::{DeltaBuilder, DeltaOperations, EmptyAttributes, OperationTransform};
 use std::sync::Arc;
@@ -126,10 +127,65 @@ impl GridViewRevisionPad {
         })
     }
 
+    pub fn get_all_sorts(&self, field_revs: &[Arc<FieldRevision>]) -> Vec<Arc<SortRevision>> {
+        self.sorts.get_objects_by_field_revs(field_revs)
+    }
+
+    /// For the moment, a field type only have one filter.
+    pub fn get_sorts(&self, field_id: &str, field_type_rev: &FieldTypeRevision) -> Vec<Arc<SortRevision>> {
+        self.sorts.get_objects(field_id, field_type_rev).unwrap_or_default()
+    }
+
+    pub fn get_sort(
+        &self,
+        field_id: &str,
+        field_type_rev: &FieldTypeRevision,
+        sort_id: &str,
+    ) -> Option<Arc<SortRevision>> {
+        self.sorts
+            .get_object(field_id, field_type_rev, |sort| sort.id == sort_id)
+    }
+
+    pub fn update_sort(
+        &mut self,
+        field_id: &str,
+        sort_rev: SortRevision,
+    ) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
+        self.modify(|view| {
+            if let Some(sort) = view
+                .sorts
+                .get_mut_object(field_id, &sort_rev.field_type, |sort| sort.id == sort_rev.id)
+            {
+                let sort = Arc::make_mut(sort);
+                sort.condition = sort_rev.condition;
+                Ok(Some(()))
+            } else {
+                Ok(None)
+            }
+        })
+    }
+
+    pub fn delete_sort(
+        &mut self,
+        sort_id: &str,
+        field_id: &str,
+        field_type: &FieldTypeRevision,
+    ) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
+        self.modify(|view| {
+            if let Some(sorts) = view.sorts.get_mut_objects(field_id, field_type) {
+                sorts.retain(|sort| sort.id != sort_id);
+                Ok(Some(()))
+            } else {
+                Ok(None)
+            }
+        })
+    }
+
     pub fn get_all_filters(&self, field_revs: &[Arc<FieldRevision>]) -> Vec<Arc<FilterRevision>> {
         self.filters.get_objects_by_field_revs(field_revs)
     }
 
+    /// For the moment, a field type only have one filter.
     pub fn get_filters(&self, field_id: &str, field_type_rev: &FieldTypeRevision) -> Vec<Arc<FilterRevision>> {
         self.filters.get_objects(field_id, field_type_rev).unwrap_or_default()
     }
@@ -176,14 +232,15 @@ impl GridViewRevisionPad {
         })
     }
 
-    pub fn delete_filter(
+    pub fn delete_filter<T: Into<FieldTypeRevision>>(
         &mut self,
         filter_id: &str,
         field_id: &str,
-        field_type: &FieldTypeRevision,
+        field_type: T,
     ) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
+        let field_type = field_type.into();
         self.modify(|view| {
-            if let Some(filters) = view.filters.get_mut_objects(field_id, field_type) {
+            if let Some(filters) = view.filters.get_mut_objects(field_id, &field_type) {
                 filters.retain(|filter| filter.id != filter_id);
                 Ok(Some(()))
             } else {

+ 4 - 4
shared-lib/grid-rev-model/src/grid_setting_rev.rs

@@ -1,4 +1,4 @@
-use crate::{FieldRevision, FieldTypeRevision, FilterRevision, GroupConfigurationRevision};
+use crate::{FieldRevision, FieldTypeRevision, FilterRevision, GroupConfigurationRevision, SortRevision};
 use indexmap::IndexMap;
 use nanoid::nanoid;
 use serde::{Deserialize, Serialize};
@@ -20,10 +20,10 @@ pub fn gen_grid_sort_id() -> String {
 }
 
 pub type FilterConfiguration = Configuration<FilterRevision>;
-pub type FilterConfigurationsByFieldId = HashMap<String, Vec<Arc<FilterRevision>>>;
-//
+
 pub type GroupConfiguration = Configuration<GroupConfigurationRevision>;
-pub type GroupConfigurationsByFieldId = HashMap<String, Vec<Arc<GroupConfigurationRevision>>>;
+
+pub type SortConfiguration = Configuration<SortRevision>;
 
 #[derive(Debug, Clone, Serialize, Deserialize, Default)]
 #[serde(transparent)]

+ 6 - 6
shared-lib/grid-rev-model/src/grid_view.rs

@@ -1,4 +1,4 @@
-use crate::{FilterConfiguration, GroupConfiguration};
+use crate::{FilterConfiguration, GroupConfiguration, SortConfiguration};
 use nanoid::nanoid;
 use serde::{Deserialize, Serialize};
 use serde_repr::*;
@@ -41,10 +41,9 @@ pub struct GridViewRevision {
 
     #[serde(default)]
     pub groups: GroupConfiguration,
-    // // For the moment, we just use the order returned from the GridRevision
-    // #[allow(dead_code)]
-    // #[serde(skip, rename = "rows")]
-    // pub row_orders: Vec<RowOrderRevision>,
+
+    #[serde(default)]
+    pub sorts: SortConfiguration,
 }
 
 impl GridViewRevision {
@@ -55,7 +54,7 @@ impl GridViewRevision {
             layout,
             filters: Default::default(),
             groups: Default::default(),
-            // row_orders: vec![],
+            sorts: Default::default(),
         }
     }
 
@@ -81,6 +80,7 @@ mod tests {
             layout: Default::default(),
             filters: Default::default(),
             groups: Default::default(),
+            sorts: Default::default(),
         };
         let s = serde_json::to_string(&grid_view_revision).unwrap();
         assert_eq!(

+ 2 - 0
shared-lib/grid-rev-model/src/lib.rs

@@ -4,6 +4,7 @@ mod grid_rev;
 mod grid_setting_rev;
 mod grid_view;
 mod group_rev;
+mod sort_rev;
 
 pub use filter_rev::*;
 pub use grid_block::*;
@@ -11,3 +12,4 @@ pub use grid_rev::*;
 pub use grid_setting_rev::*;
 pub use grid_view::*;
 pub use group_rev::*;
+pub use sort_rev::*;

+ 10 - 0
shared-lib/grid-rev-model/src/sort_rev.rs

@@ -0,0 +1,10 @@
+use crate::FieldTypeRevision;
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)]
+pub struct SortRevision {
+    pub id: String,
+    pub field_id: String,
+    pub field_type: FieldTypeRevision,
+    pub condition: u8,
+}