mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #1268 from AppFlowy-IO/fix/edit_no_status_card
Fix/edit no status card
This commit is contained in:
@ -54,7 +54,7 @@ impl GridBlockManager {
|
|||||||
|
|
||||||
pub(crate) async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult<Arc<GridBlockRevisionEditor>> {
|
pub(crate) async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult<Arc<GridBlockRevisionEditor>> {
|
||||||
let block_id = self.persistence.get_block_id(row_id)?;
|
let block_id = self.persistence.get_block_id(row_id)?;
|
||||||
Ok(self.get_block_editor(&block_id).await?)
|
self.get_block_editor(&block_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip(self, start_row_id), err)]
|
#[tracing::instrument(level = "trace", skip(self, start_row_id), err)]
|
||||||
|
@ -30,8 +30,7 @@ impl GridViewRowDelegate for Arc<GridBlockManager> {
|
|||||||
let blocks = block_manager.get_block_snapshots(None).await.unwrap();
|
let blocks = block_manager.get_block_snapshots(None).await.unwrap();
|
||||||
blocks
|
blocks
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|block| block.row_revs)
|
.flat_map(|block| block.row_revs)
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<Arc<RowRevision>>>()
|
.collect::<Vec<Arc<RowRevision>>>()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -113,11 +113,15 @@ impl AnyCellData {
|
|||||||
/// * Use URLCellData to parse the data when the FieldType is URL.
|
/// * Use URLCellData to parse the data when the FieldType is URL.
|
||||||
/// * Use String to parse the data when the FieldType is RichText, Number, or Checkbox.
|
/// * Use String to parse the data when the FieldType is RichText, Number, or Checkbox.
|
||||||
/// * Check out the implementation of CellDataOperation trait for more information.
|
/// * Check out the implementation of CellDataOperation trait for more information.
|
||||||
#[derive(Default)]
|
#[derive(Default, Debug)]
|
||||||
pub struct CellBytes(pub Bytes);
|
pub struct CellBytes(pub Bytes);
|
||||||
|
|
||||||
|
pub trait CellDataIsEmpty {
|
||||||
|
fn is_empty(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait CellBytesParser {
|
pub trait CellBytesParser {
|
||||||
type Object;
|
type Object: CellDataIsEmpty;
|
||||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object>;
|
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::services::cell::{CellBytesParser, FromCellString};
|
use crate::services::cell::{CellBytesParser, CellDataIsEmpty, FromCellString};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@ -61,6 +61,13 @@ impl ToString for CheckboxCellData {
|
|||||||
self.0.clone()
|
self.0.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CellDataIsEmpty for CheckboxCellData {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.0.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CheckboxCellDataParser();
|
pub struct CheckboxCellDataParser();
|
||||||
impl CellBytesParser for CheckboxCellDataParser {
|
impl CellBytesParser for CheckboxCellDataParser {
|
||||||
type Object = CheckboxCellData;
|
type Object = CheckboxCellData;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::CellChangesetPB;
|
use crate::entities::CellChangesetPB;
|
||||||
use crate::entities::{GridCellIdPB, GridCellIdParams};
|
use crate::entities::{GridCellIdPB, GridCellIdParams};
|
||||||
use crate::services::cell::{CellBytesParser, FromCellChangeset, FromCellString};
|
use crate::services::cell::{CellBytesParser, CellDataIsEmpty, FromCellChangeset, FromCellString};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||||
@ -200,6 +200,12 @@ impl std::default::Default for TimeFormat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CellDataIsEmpty for DateCellDataPB {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.date.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DateCellDataParser();
|
pub struct DateCellDataParser();
|
||||||
impl CellBytesParser for DateCellDataParser {
|
impl CellBytesParser for DateCellDataParser {
|
||||||
type Object = DateCellDataPB;
|
type Object = DateCellDataPB;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::services::cell::{CellBytesCustomParser, CellBytesParser};
|
use crate::services::cell::{CellBytesCustomParser, CellBytesParser, CellDataIsEmpty};
|
||||||
use crate::services::field::number_currency::Currency;
|
use crate::services::field::number_currency::Currency;
|
||||||
use crate::services::field::{strip_currency_symbol, NumberFormat, STRIP_SYMBOL};
|
use crate::services::field::{strip_currency_symbol, NumberFormat, STRIP_SYMBOL};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
@ -93,6 +93,12 @@ impl ToString for NumberCellData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CellDataIsEmpty for NumberCellData {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.decimal.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
pub struct NumberCellDataParser();
|
pub struct NumberCellDataParser();
|
||||||
impl CellBytesParser for NumberCellDataParser {
|
impl CellBytesParser for NumberCellDataParser {
|
||||||
type Object = NumberCellData;
|
type Object = NumberCellData;
|
||||||
|
@ -117,12 +117,12 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder {
|
|||||||
match field_type {
|
match field_type {
|
||||||
FieldType::Checkbox => {
|
FieldType::Checkbox => {
|
||||||
//Add Yes and No options if it's not exist.
|
//Add Yes and No options if it's not exist.
|
||||||
if self.0.options.iter().find(|option| option.name == CHECK).is_none() {
|
if !self.0.options.iter().any(|option| option.name == CHECK) {
|
||||||
let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
|
let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
|
||||||
self.0.options.push(check_option);
|
self.0.options.push(check_option);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.0.options.iter().find(|option| option.name == UNCHECK).is_none() {
|
if !self.0.options.iter().any(|option| option.name == UNCHECK) {
|
||||||
let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
|
let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
|
||||||
self.0.options.push(uncheck_option);
|
self.0.options.push(uncheck_option);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams};
|
use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams};
|
||||||
use crate::services::cell::{CellBytes, CellBytesParser, CellData, CellDisplayable, FromCellChangeset, FromCellString};
|
use crate::services::cell::{
|
||||||
|
CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString,
|
||||||
|
};
|
||||||
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||||
@ -233,7 +235,7 @@ impl ToString for SelectOptionIds {
|
|||||||
impl std::convert::From<Option<String>> for SelectOptionIds {
|
impl std::convert::From<Option<String>> for SelectOptionIds {
|
||||||
fn from(s: Option<String>) -> Self {
|
fn from(s: Option<String>) -> Self {
|
||||||
match s {
|
match s {
|
||||||
None => Self { 0: vec![] },
|
None => Self(vec![]),
|
||||||
Some(s) => Self::from(s),
|
Some(s) => Self::from(s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,6 +254,13 @@ impl std::ops::DerefMut for SelectOptionIds {
|
|||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CellDataIsEmpty for SelectOptionIds {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.0.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SelectOptionIdsParser();
|
pub struct SelectOptionIdsParser();
|
||||||
impl CellBytesParser for SelectOptionIdsParser {
|
impl CellBytesParser for SelectOptionIdsParser {
|
||||||
type Object = SelectOptionIds;
|
type Object = SelectOptionIds;
|
||||||
@ -263,6 +272,12 @@ impl CellBytesParser for SelectOptionIdsParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CellDataIsEmpty for SelectOptionCellDataPB {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.select_options.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SelectOptionCellDataParser();
|
pub struct SelectOptionCellDataParser();
|
||||||
impl CellBytesParser for SelectOptionCellDataParser {
|
impl CellBytesParser for SelectOptionCellDataParser {
|
||||||
type Object = SelectOptionCellDataPB;
|
type Object = SelectOptionCellDataPB;
|
||||||
|
@ -61,7 +61,6 @@ impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for SingleSel
|
|||||||
_cell_rev: Option<CellRevision>,
|
_cell_rev: Option<CellRevision>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> Result<String, FlowyError> {
|
||||||
let content_changeset = changeset.try_into_inner()?;
|
let content_changeset = changeset.try_into_inner()?;
|
||||||
let new_cell_data: String;
|
|
||||||
|
|
||||||
let mut insert_option_ids = content_changeset
|
let mut insert_option_ids = content_changeset
|
||||||
.insert_option_ids
|
.insert_option_ids
|
||||||
@ -73,14 +72,12 @@ impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for SingleSel
|
|||||||
// Sometimes, the insert_option_ids may contain list of option ids. For example,
|
// Sometimes, the insert_option_ids may contain list of option ids. For example,
|
||||||
// copy/paste a ids string.
|
// copy/paste a ids string.
|
||||||
if insert_option_ids.is_empty() {
|
if insert_option_ids.is_empty() {
|
||||||
new_cell_data = "".to_string()
|
Ok("".to_string())
|
||||||
} else {
|
} else {
|
||||||
// Just take the first select option
|
// Just take the first select option
|
||||||
let _ = insert_option_ids.drain(1..);
|
let _ = insert_option_ids.drain(1..);
|
||||||
new_cell_data = insert_option_ids.pop().unwrap();
|
Ok(insert_option_ids.pop().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(new_cell_data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,12 +106,12 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder {
|
|||||||
match field_type {
|
match field_type {
|
||||||
FieldType::Checkbox => {
|
FieldType::Checkbox => {
|
||||||
//add Yes and No options if it's not exist.
|
//add Yes and No options if it's not exist.
|
||||||
if self.0.options.iter().find(|option| option.name == CHECK).is_none() {
|
if !self.0.options.iter().any(|option| option.name == CHECK) {
|
||||||
let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
|
let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
|
||||||
self.0.options.push(check_option);
|
self.0.options.push(check_option);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.0.options.iter().find(|option| option.name == UNCHECK).is_none() {
|
if !self.0.options.iter().any(|option| option.name == UNCHECK) {
|
||||||
let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
|
let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
|
||||||
self.0.options.push(uncheck_option);
|
self.0.options.push(uncheck_option);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::entities::FieldType;
|
use crate::entities::FieldType;
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{
|
use crate::services::cell::{
|
||||||
decode_cell_data_to_string, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataOperation,
|
decode_cell_data_to_string, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataIsEmpty,
|
||||||
CellDisplayable, FromCellString,
|
CellDataOperation, CellDisplayable, FromCellString,
|
||||||
};
|
};
|
||||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
@ -125,6 +125,12 @@ impl ToString for TextCellData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CellDataIsEmpty for TextCellData {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.0.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct TextCellDataParser();
|
pub struct TextCellDataParser();
|
||||||
impl CellBytesParser for TextCellDataParser {
|
impl CellBytesParser for TextCellDataParser {
|
||||||
type Object = TextCellData;
|
type Object = TextCellData;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::services::cell::{CellBytesParser, FromCellString};
|
use crate::services::cell::{CellBytesParser, CellDataIsEmpty, FromCellString};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{internal_error, FlowyResult};
|
use flowy_error::{internal_error, FlowyResult};
|
||||||
@ -26,6 +26,12 @@ impl URLCellDataPB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CellDataIsEmpty for URLCellDataPB {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.content.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct URLCellDataParser();
|
pub struct URLCellDataParser();
|
||||||
impl CellBytesParser for URLCellDataParser {
|
impl CellBytesParser for URLCellDataParser {
|
||||||
type Object = URLCellDataPB;
|
type Object = URLCellDataPB;
|
||||||
|
@ -410,7 +410,7 @@ impl GridRevisionEditor {
|
|||||||
pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> {
|
pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> {
|
||||||
let row_id = changeset.row_id.clone();
|
let row_id = changeset.row_id.clone();
|
||||||
let _ = self.block_manager.update_row(changeset).await?;
|
let _ = self.block_manager.update_row(changeset).await?;
|
||||||
self.view_manager.did_update_row(&row_id).await;
|
self.view_manager.did_update_cell(&row_id).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +504,7 @@ impl GridRevisionEditor {
|
|||||||
content,
|
content,
|
||||||
};
|
};
|
||||||
let _ = self.block_manager.update_cell(cell_changeset).await?;
|
let _ = self.block_manager.update_cell(cell_changeset).await?;
|
||||||
self.view_manager.did_update_cell(&row_id, &field_id).await;
|
self.view_manager.did_update_cell(&row_id).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,15 +123,15 @@ impl GridViewRevisionEditor {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
tracing::trace!("Delete row in view changeset: {:?}", changesets);
|
||||||
if let Some(changesets) = changesets {
|
if let Some(changesets) = changesets {
|
||||||
tracing::trace!("{:?}", changesets);
|
|
||||||
for changeset in changesets {
|
for changeset in changesets {
|
||||||
self.notify_did_update_group(changeset).await;
|
self.notify_did_update_group(changeset).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn did_update_view_row(&self, row_rev: &RowRevision) {
|
pub(crate) async fn did_update_view_cell(&self, row_rev: &RowRevision) {
|
||||||
let changesets = self
|
let changesets = self
|
||||||
.mut_group_controller(|group_controller, field_rev| {
|
.mut_group_controller(|group_controller, field_rev| {
|
||||||
group_controller.did_update_group_row(row_rev, &field_rev)
|
group_controller.did_update_group_row(row_rev, &field_rev)
|
||||||
@ -539,11 +539,10 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc<Field
|
|||||||
.map(|filters_by_field_id| {
|
.map(|filters_by_field_id| {
|
||||||
filters_by_field_id
|
filters_by_field_id
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, v)| {
|
.flat_map(|(_, v)| {
|
||||||
let repeated_filter: RepeatedGridFilterConfigurationPB = v.into();
|
let repeated_filter: RepeatedGridFilterConfigurationPB = v.into();
|
||||||
repeated_filter.items
|
repeated_filter.items
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<GridFilterConfigurationPB>>()
|
.collect::<Vec<GridFilterConfigurationPB>>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
@ -553,11 +552,10 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc<Field
|
|||||||
.map(|groups_by_field_id| {
|
.map(|groups_by_field_id| {
|
||||||
groups_by_field_id
|
groups_by_field_id
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, v)| {
|
.flat_map(|(_, v)| {
|
||||||
let repeated_group: RepeatedGridGroupConfigurationPB = v.into();
|
let repeated_group: RepeatedGridGroupConfigurationPB = v.into();
|
||||||
repeated_group.items
|
repeated_group.items
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<GridGroupConfigurationPB>>()
|
.collect::<Vec<GridGroupConfigurationPB>>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
@ -77,15 +77,15 @@ impl GridViewManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert/Delete the group's row if the corresponding data was changed.
|
/// Insert/Delete the group's row if the corresponding cell data was changed.
|
||||||
pub(crate) async fn did_update_row(&self, row_id: &str) {
|
pub(crate) async fn did_update_cell(&self, row_id: &str) {
|
||||||
match self.row_delegate.gv_get_row_rev(row_id).await {
|
match self.row_delegate.gv_get_row_rev(row_id).await {
|
||||||
None => {
|
None => {
|
||||||
tracing::warn!("Can not find the row in grid view");
|
tracing::warn!("Can not find the row in grid view");
|
||||||
}
|
}
|
||||||
Some(row_rev) => {
|
Some(row_rev) => {
|
||||||
for view_editor in self.view_editors.iter() {
|
for view_editor in self.view_editors.iter() {
|
||||||
view_editor.did_update_view_row(&row_rev).await;
|
view_editor.did_update_view_cell(&row_rev).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,10 +97,6 @@ impl GridViewManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn did_update_cell(&self, row_id: &str, _field_id: &str) {
|
|
||||||
self.did_update_row(row_id).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn did_delete_row(&self, row_rev: Arc<RowRevision>) {
|
pub(crate) async fn did_delete_row(&self, row_rev: Arc<RowRevision>) {
|
||||||
for view_editor in self.view_editors.iter() {
|
for view_editor in self.view_editors.iter() {
|
||||||
view_editor.did_delete_view_row(&row_rev).await;
|
view_editor.did_delete_view_row(&row_rev).await;
|
||||||
|
@ -1,19 +1,79 @@
|
|||||||
use crate::entities::GroupChangesetPB;
|
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB};
|
||||||
|
use crate::services::cell::CellDataIsEmpty;
|
||||||
use crate::services::group::controller::MoveGroupRowContext;
|
use crate::services::group::controller::MoveGroupRowContext;
|
||||||
use flowy_grid_data_model::revision::{CellRevision, RowRevision};
|
use crate::services::group::Group;
|
||||||
|
use flowy_error::FlowyResult;
|
||||||
|
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, RowRevision};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub trait GroupAction: Send + Sync {
|
/// Using polymorphism to provides the customs action for different group controller.
|
||||||
type CellDataType;
|
///
|
||||||
|
/// For example, the `CheckboxGroupController` implements this trait to provide custom behavior.
|
||||||
|
///
|
||||||
|
pub trait GroupControllerCustomActions: Send + Sync {
|
||||||
|
type CellDataType: CellDataIsEmpty;
|
||||||
|
/// Returns the a value of the cell, default value is None
|
||||||
|
///
|
||||||
|
/// Determine which group the row is placed in based on the data of the cell. If the cell data
|
||||||
|
/// is None. The row will be put in to the `No status` group
|
||||||
|
///
|
||||||
fn default_cell_rev(&self) -> Option<CellRevision> {
|
fn default_cell_rev(&self) -> Option<CellRevision> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn use_default_group(&self) -> bool {
|
|
||||||
true
|
/// Returns a bool value to determine whether the group should contain this cell or not.
|
||||||
}
|
|
||||||
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
|
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
|
||||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
|
|
||||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
|
/// Adds or removes a row if the cell data match the group filter.
|
||||||
// Move row from one group to another
|
/// It gets called after editing the cell or row
|
||||||
|
///
|
||||||
|
fn add_or_remove_row_in_groups_if_match(
|
||||||
|
&mut self,
|
||||||
|
row_rev: &RowRevision,
|
||||||
|
cell_data: &Self::CellDataType,
|
||||||
|
) -> Vec<GroupChangesetPB>;
|
||||||
|
|
||||||
|
/// Deletes the row from the group
|
||||||
|
fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
|
||||||
|
|
||||||
|
/// Move row from one group to another
|
||||||
fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupChangesetPB>;
|
fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupChangesetPB>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the shared actions any group controller can perform.
|
||||||
|
pub trait GroupControllerSharedActions: 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<()>;
|
||||||
|
|
||||||
|
/// Insert/Remove 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>>;
|
||||||
|
|
||||||
|
/// Remove the row from the group if the row gets deleted
|
||||||
|
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>>;
|
||||||
|
|
||||||
|
/// Update the group if the corresponding field is changed
|
||||||
|
fn did_update_group_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>>;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::entities::{GroupPB, GroupViewChangesetPB};
|
use crate::entities::{GroupPB, GroupViewChangesetPB};
|
||||||
use crate::services::group::{default_group_configuration, make_no_status_group, GeneratedGroupConfig, Group};
|
use crate::services::group::{default_group_configuration, GeneratedGroupContext, Group};
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{
|
||||||
FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision,
|
FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision,
|
||||||
@ -118,8 +118,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate mut the groups. The default group will be the last one that get mutated.
|
/// Iterate mut the groups without `No status` group
|
||||||
pub(crate) fn iter_mut_all_groups(&mut self, mut each: impl FnMut(&mut Group)) {
|
pub(crate) fn iter_mut_status_groups(&mut self, mut each: impl FnMut(&mut Group)) {
|
||||||
|
self.groups_map.iter_mut().for_each(|(_, group)| {
|
||||||
|
if group.id != self.field_rev.id {
|
||||||
|
each(group);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn iter_mut_groups(&mut self, mut each: impl FnMut(&mut Group)) {
|
||||||
self.groups_map.iter_mut().for_each(|(_, group)| {
|
self.groups_map.iter_mut().for_each(|(_, group)| {
|
||||||
each(group);
|
each(group);
|
||||||
});
|
});
|
||||||
@ -172,14 +180,19 @@ where
|
|||||||
/// [GroupConfigurationRevision] as old groups. The old groups and the new groups will be merged
|
/// [GroupConfigurationRevision] as old groups. The old groups and the new groups will be merged
|
||||||
/// while keeping the order of the old groups.
|
/// while keeping the order of the old groups.
|
||||||
///
|
///
|
||||||
#[tracing::instrument(level = "trace", skip(self, generated_group_configs), err)]
|
#[tracing::instrument(level = "trace", skip(self, generated_group_context), err)]
|
||||||
pub(crate) fn init_groups(
|
pub(crate) fn init_groups(
|
||||||
&mut self,
|
&mut self,
|
||||||
generated_group_configs: Vec<GeneratedGroupConfig>,
|
generated_group_context: GeneratedGroupContext,
|
||||||
) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
||||||
|
let GeneratedGroupContext {
|
||||||
|
no_status_group,
|
||||||
|
group_configs,
|
||||||
|
} = generated_group_context;
|
||||||
|
|
||||||
let mut new_groups = vec![];
|
let mut new_groups = vec![];
|
||||||
let mut filter_content_map = HashMap::new();
|
let mut filter_content_map = HashMap::new();
|
||||||
generated_group_configs.into_iter().for_each(|generate_group| {
|
group_configs.into_iter().for_each(|generate_group| {
|
||||||
filter_content_map.insert(generate_group.group_rev.id.clone(), generate_group.filter_content);
|
filter_content_map.insert(generate_group.group_rev.id.clone(), generate_group.filter_content);
|
||||||
new_groups.push(generate_group.group_rev);
|
new_groups.push(generate_group.group_rev);
|
||||||
});
|
});
|
||||||
@ -190,12 +203,9 @@ where
|
|||||||
old_groups.clear();
|
old_groups.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// When grouping by a new field, there is no `No status` group. So it needs
|
|
||||||
// to insert a `No status` group at index 0
|
|
||||||
// The `No status` group index is initialized to 0
|
// The `No status` group index is initialized to 0
|
||||||
//
|
if let Some(no_status_group) = no_status_group {
|
||||||
if !old_groups.iter().any(|group| group.id == self.field_rev.id) {
|
old_groups.insert(0, no_status_group);
|
||||||
old_groups.insert(0, make_no_status_group(&self.field_rev));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The `all_group_revs` is the combination of the new groups and old groups
|
// The `all_group_revs` is the combination of the new groups and old groups
|
||||||
@ -236,9 +246,9 @@ where
|
|||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
let mut old_group = configuration.groups.get_mut(pos).unwrap();
|
let mut old_group = configuration.groups.get_mut(pos).unwrap();
|
||||||
// Take the old group setting
|
// Take the old group setting
|
||||||
group_rev.update_with_other(&old_group);
|
group_rev.update_with_other(old_group);
|
||||||
if !is_changed {
|
if !is_changed {
|
||||||
is_changed = is_group_changed(group_rev, &old_group);
|
is_changed = is_group_changed(group_rev, old_group);
|
||||||
}
|
}
|
||||||
// Consider the the name of the `group_rev` as the newest.
|
// Consider the the name of the `group_rev` as the newest.
|
||||||
old_group.name = group_rev.name.clone();
|
old_group.name = group_rev.name.clone();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB};
|
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB};
|
||||||
use crate::services::cell::{decode_any_cell_data, CellBytesParser};
|
use crate::services::cell::{decode_any_cell_data, CellBytesParser, CellDataIsEmpty};
|
||||||
use crate::services::group::action::GroupAction;
|
use crate::services::group::action::{GroupControllerCustomActions, GroupControllerSharedActions};
|
||||||
use crate::services::group::configuration::GroupContext;
|
use crate::services::group::configuration::GroupContext;
|
||||||
use crate::services::group::entities::Group;
|
use crate::services::group::entities::Group;
|
||||||
use flowy_error::FlowyResult;
|
use flowy_error::FlowyResult;
|
||||||
@ -18,7 +18,7 @@ use std::sync::Arc;
|
|||||||
/// If the [FieldType] doesn't implement its group controller, then the [DefaultGroupController] will
|
/// If the [FieldType] doesn't implement its group controller, then the [DefaultGroupController] will
|
||||||
/// be used.
|
/// be used.
|
||||||
///
|
///
|
||||||
pub trait GroupController: GroupControllerActions + Send + Sync {
|
pub trait GroupController: GroupControllerSharedActions + Send + Sync {
|
||||||
fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
|
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);
|
fn did_create_row(&mut self, row_pb: &RowPB, group_id: &str);
|
||||||
}
|
}
|
||||||
@ -29,10 +29,15 @@ pub trait GroupGenerator {
|
|||||||
type TypeOptionType;
|
type TypeOptionType;
|
||||||
|
|
||||||
fn generate_groups(
|
fn generate_groups(
|
||||||
field_id: &str,
|
field_rev: &FieldRevision,
|
||||||
group_ctx: &Self::Context,
|
group_ctx: &Self::Context,
|
||||||
type_option: &Option<Self::TypeOptionType>,
|
type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroupConfig>;
|
) -> GeneratedGroupContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GeneratedGroupContext {
|
||||||
|
pub no_status_group: Option<GroupRevision>,
|
||||||
|
pub group_configs: Vec<GeneratedGroupConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GeneratedGroupConfig {
|
pub struct GeneratedGroupConfig {
|
||||||
@ -47,45 +52,6 @@ pub struct MoveGroupRowContext<'a> {
|
|||||||
pub to_group_id: &'a str,
|
pub to_group_id: &'a str,
|
||||||
pub to_row_id: Option<String>,
|
pub to_row_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<()>;
|
|
||||||
|
|
||||||
/// 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>>;
|
|
||||||
|
|
||||||
/// 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>>;
|
|
||||||
|
|
||||||
/// 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]
|
/// C: represents the group configuration that impl [GroupConfigurationSerde]
|
||||||
/// T: the type-option data deserializer that impl [TypeOptionDataDeserializer]
|
/// T: the type-option data deserializer that impl [TypeOptionDataDeserializer]
|
||||||
/// G: the group generator, [GroupGenerator]
|
/// G: the group generator, [GroupGenerator]
|
||||||
@ -106,8 +72,8 @@ where
|
|||||||
{
|
{
|
||||||
pub async fn new(field_rev: &Arc<FieldRevision>, mut configuration: GroupContext<C>) -> FlowyResult<Self> {
|
pub async fn new(field_rev: &Arc<FieldRevision>, mut configuration: GroupContext<C>) -> FlowyResult<Self> {
|
||||||
let type_option = field_rev.get_type_option::<T>(field_rev.ty);
|
let type_option = field_rev.get_type_option::<T>(field_rev.ty);
|
||||||
let groups = G::generate_groups(&field_rev.id, &configuration, &type_option);
|
let generated_group_context = G::generate_groups(field_rev, &configuration, &type_option);
|
||||||
let _ = configuration.init_groups(groups)?;
|
let _ = configuration.init_groups(generated_group_context)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
field_id: field_rev.id.clone(),
|
field_id: field_rev.id.clone(),
|
||||||
@ -186,30 +152,21 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, T, G, P> GroupControllerActions for GenericGroupController<C, T, G, P>
|
impl<C, T, G, P> GroupControllerSharedActions for GenericGroupController<C, T, G, P>
|
||||||
where
|
where
|
||||||
P: CellBytesParser,
|
P: CellBytesParser,
|
||||||
C: GroupConfigurationContentSerde,
|
C: GroupConfigurationContentSerde,
|
||||||
T: TypeOptionDataDeserializer,
|
T: TypeOptionDataDeserializer,
|
||||||
G: GroupGenerator<Context = GroupContext<C>, TypeOptionType = T>,
|
G: GroupGenerator<Context = GroupContext<C>, TypeOptionType = T>,
|
||||||
|
|
||||||
Self: GroupAction<CellDataType = P::Object>,
|
Self: GroupControllerCustomActions<CellDataType = P::Object>,
|
||||||
{
|
{
|
||||||
fn field_id(&self) -> &str {
|
fn field_id(&self) -> &str {
|
||||||
&self.field_id
|
&self.field_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn groups(&self) -> Vec<Group> {
|
fn groups(&self) -> Vec<Group> {
|
||||||
if self.use_default_group() {
|
self.group_ctx.groups().into_iter().cloned().collect()
|
||||||
self.group_ctx.groups().into_iter().cloned().collect()
|
|
||||||
} else {
|
|
||||||
self.group_ctx
|
|
||||||
.groups()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|group| group.id != self.field_id)
|
|
||||||
.cloned()
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
||||||
@ -269,17 +226,14 @@ where
|
|||||||
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
||||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
|
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
|
||||||
let cell_data = cell_bytes.parser::<P>()?;
|
let cell_data = cell_bytes.parser::<P>()?;
|
||||||
let mut changesets = self.add_row_if_match(row_rev, &cell_data);
|
let mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data);
|
||||||
|
|
||||||
if self.use_default_group() {
|
if let Some(default_group_changeset) = self.update_default_group(row_rev, &changesets) {
|
||||||
if let Some(default_group_changeset) = self.update_default_group(row_rev, &changesets) {
|
tracing::trace!("default_group_changeset: {}", default_group_changeset);
|
||||||
tracing::trace!("default_group_changeset: {}", default_group_changeset);
|
if !default_group_changeset.is_empty() {
|
||||||
if !default_group_changeset.is_empty() {
|
changesets.push(default_group_changeset);
|
||||||
changesets.push(default_group_changeset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(changesets)
|
Ok(changesets)
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
@ -291,18 +245,30 @@ where
|
|||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<Vec<GroupChangesetPB>> {
|
) -> FlowyResult<Vec<GroupChangesetPB>> {
|
||||||
// if the cell_rev is none, then the row must be crated from the default group.
|
// if the cell_rev is none, then the row must in the default group.
|
||||||
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
||||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
|
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
|
||||||
let cell_data = cell_bytes.parser::<P>()?;
|
let cell_data = cell_bytes.parser::<P>()?;
|
||||||
Ok(self.remove_row_if_match(row_rev, &cell_data))
|
if !cell_data.is_empty() {
|
||||||
} else if let Some(group) = self.group_ctx.get_no_status_group() {
|
tracing::error!("did_delete_delete_row {:?}", cell_rev.data);
|
||||||
Ok(vec![GroupChangesetPB::delete(
|
return Ok(self.delete_row(row_rev, &cell_data));
|
||||||
group.id.clone(),
|
}
|
||||||
vec![row_rev.id.clone()],
|
}
|
||||||
)])
|
|
||||||
} else {
|
match self.group_ctx.get_no_status_group() {
|
||||||
Ok(vec![])
|
None => {
|
||||||
|
tracing::error!("Unexpected None value. It should have the no status group");
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
Some(no_status_group) => {
|
||||||
|
if !no_status_group.contains_row(&row_rev.id) {
|
||||||
|
tracing::error!("The row: {} should be in the no status group", row_rev.id);
|
||||||
|
}
|
||||||
|
Ok(vec![GroupChangesetPB::delete(
|
||||||
|
no_status_group.id.clone(),
|
||||||
|
vec![row_rev.id.clone()],
|
||||||
|
)])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use crate::entities::{GroupChangesetPB, InsertedRowPB, RowPB};
|
use crate::entities::{GroupChangesetPB, InsertedRowPB, RowPB};
|
||||||
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
|
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
|
||||||
use crate::services::group::action::GroupAction;
|
use crate::services::group::action::GroupControllerCustomActions;
|
||||||
use crate::services::group::configuration::GroupContext;
|
use crate::services::group::configuration::GroupContext;
|
||||||
use crate::services::group::controller::{
|
use crate::services::group::controller::{
|
||||||
GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext,
|
GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::services::cell::insert_checkbox_cell;
|
use crate::services::cell::insert_checkbox_cell;
|
||||||
use crate::services::group::{move_group_row, GeneratedGroupConfig};
|
use crate::services::group::{move_group_row, GeneratedGroupConfig, GeneratedGroupContext};
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{
|
||||||
CellRevision, CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision,
|
CellRevision, CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision,
|
||||||
};
|
};
|
||||||
@ -21,16 +21,12 @@ pub type CheckboxGroupController = GenericGroupController<
|
|||||||
|
|
||||||
pub type CheckboxGroupContext = GroupContext<CheckboxGroupConfigurationRevision>;
|
pub type CheckboxGroupContext = GroupContext<CheckboxGroupConfigurationRevision>;
|
||||||
|
|
||||||
impl GroupAction for CheckboxGroupController {
|
impl GroupControllerCustomActions for CheckboxGroupController {
|
||||||
type CellDataType = CheckboxCellData;
|
type CellDataType = CheckboxCellData;
|
||||||
fn default_cell_rev(&self) -> Option<CellRevision> {
|
fn default_cell_rev(&self) -> Option<CellRevision> {
|
||||||
Some(CellRevision::new(UNCHECK.to_string()))
|
Some(CellRevision::new(UNCHECK.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_default_group(&self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool {
|
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool {
|
||||||
if cell_data.is_check() {
|
if cell_data.is_check() {
|
||||||
content == CHECK
|
content == CHECK
|
||||||
@ -39,9 +35,13 @@ impl GroupAction for CheckboxGroupController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
fn add_or_remove_row_in_groups_if_match(
|
||||||
|
&mut self,
|
||||||
|
row_rev: &RowRevision,
|
||||||
|
cell_data: &Self::CellDataType,
|
||||||
|
) -> Vec<GroupChangesetPB> {
|
||||||
let mut changesets = vec![];
|
let mut changesets = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_status_groups(|group| {
|
||||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||||
let is_not_contained = !group.contains_row(&row_rev.id);
|
let is_not_contained = !group.contains_row(&row_rev.id);
|
||||||
if group.id == CHECK {
|
if group.id == CHECK {
|
||||||
@ -81,9 +81,9 @@ impl GroupAction for CheckboxGroupController {
|
|||||||
changesets
|
changesets
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
fn delete_row(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||||
let mut changesets = vec![];
|
let mut changesets = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_groups(|group| {
|
||||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||||
if group.contains_row(&row_rev.id) {
|
if group.contains_row(&row_rev.id) {
|
||||||
changeset.deleted_rows.push(row_rev.id.clone());
|
changeset.deleted_rows.push(row_rev.id.clone());
|
||||||
@ -99,7 +99,7 @@ impl GroupAction for CheckboxGroupController {
|
|||||||
|
|
||||||
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||||
let mut group_changeset = vec![];
|
let mut group_changeset = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_groups(|group| {
|
||||||
if let Some(changeset) = move_group_row(group, &mut context) {
|
if let Some(changeset) = move_group_row(group, &mut context) {
|
||||||
group_changeset.push(changeset);
|
group_changeset.push(changeset);
|
||||||
}
|
}
|
||||||
@ -133,10 +133,10 @@ impl GroupGenerator for CheckboxGroupGenerator {
|
|||||||
type TypeOptionType = CheckboxTypeOptionPB;
|
type TypeOptionType = CheckboxTypeOptionPB;
|
||||||
|
|
||||||
fn generate_groups(
|
fn generate_groups(
|
||||||
_field_id: &str,
|
_field_rev: &FieldRevision,
|
||||||
_group_ctx: &Self::Context,
|
_group_ctx: &Self::Context,
|
||||||
_type_option: &Option<Self::TypeOptionType>,
|
_type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroupConfig> {
|
) -> GeneratedGroupContext {
|
||||||
let check_group = GeneratedGroupConfig {
|
let check_group = GeneratedGroupConfig {
|
||||||
group_rev: GroupRevision::new(CHECK.to_string(), "".to_string()),
|
group_rev: GroupRevision::new(CHECK.to_string(), "".to_string()),
|
||||||
filter_content: CHECK.to_string(),
|
filter_content: CHECK.to_string(),
|
||||||
@ -146,6 +146,10 @@ impl GroupGenerator for CheckboxGroupGenerator {
|
|||||||
group_rev: GroupRevision::new(UNCHECK.to_string(), "".to_string()),
|
group_rev: GroupRevision::new(UNCHECK.to_string(), "".to_string()),
|
||||||
filter_content: UNCHECK.to_string(),
|
filter_content: UNCHECK.to_string(),
|
||||||
};
|
};
|
||||||
vec![check_group, uncheck_group]
|
|
||||||
|
GeneratedGroupContext {
|
||||||
|
no_status_group: None,
|
||||||
|
group_configs: vec![check_group, uncheck_group],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
|
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
|
||||||
use crate::services::group::{Group, GroupController, GroupControllerActions, MoveGroupRowContext};
|
use crate::services::group::action::GroupControllerSharedActions;
|
||||||
|
use crate::services::group::{Group, GroupController, MoveGroupRowContext};
|
||||||
use flowy_error::FlowyResult;
|
use flowy_error::FlowyResult;
|
||||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -30,7 +31,7 @@ impl DefaultGroupController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GroupControllerActions for DefaultGroupController {
|
impl GroupControllerSharedActions for DefaultGroupController {
|
||||||
fn field_id(&self) -> &str {
|
fn field_id(&self) -> &str {
|
||||||
&self.field_id
|
&self.field_id
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use crate::entities::{GroupChangesetPB, RowPB};
|
use crate::entities::{GroupChangesetPB, RowPB};
|
||||||
use crate::services::cell::insert_select_option_cell;
|
use crate::services::cell::insert_select_option_cell;
|
||||||
use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser};
|
use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser};
|
||||||
use crate::services::group::action::GroupAction;
|
use crate::services::group::action::GroupControllerCustomActions;
|
||||||
|
|
||||||
use crate::services::group::controller::{
|
use crate::services::group::controller::{
|
||||||
GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext,
|
GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext,
|
||||||
};
|
};
|
||||||
use crate::services::group::controller_impls::select_option_controller::util::*;
|
use crate::services::group::controller_impls::select_option_controller::util::*;
|
||||||
|
|
||||||
use crate::services::group::GeneratedGroupConfig;
|
use crate::services::group::{make_no_status_group, GeneratedGroupContext};
|
||||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
||||||
|
|
||||||
// MultiSelect
|
// MultiSelect
|
||||||
@ -19,26 +19,30 @@ pub type MultiSelectGroupController = GenericGroupController<
|
|||||||
SelectOptionCellDataParser,
|
SelectOptionCellDataParser,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
impl GroupAction for MultiSelectGroupController {
|
impl GroupControllerCustomActions for MultiSelectGroupController {
|
||||||
type CellDataType = SelectOptionCellDataPB;
|
type CellDataType = SelectOptionCellDataPB;
|
||||||
|
|
||||||
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||||
cell_data.select_options.iter().any(|option| option.id == content)
|
cell_data.select_options.iter().any(|option| option.id == content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
fn add_or_remove_row_in_groups_if_match(
|
||||||
|
&mut self,
|
||||||
|
row_rev: &RowRevision,
|
||||||
|
cell_data: &Self::CellDataType,
|
||||||
|
) -> Vec<GroupChangesetPB> {
|
||||||
let mut changesets = vec![];
|
let mut changesets = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_status_groups(|group| {
|
||||||
if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) {
|
if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row_rev) {
|
||||||
changesets.push(changeset);
|
changesets.push(changeset);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
changesets
|
changesets
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||||
let mut changesets = vec![];
|
let mut changesets = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_status_groups(|group| {
|
||||||
if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) {
|
if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) {
|
||||||
changesets.push(changeset);
|
changesets.push(changeset);
|
||||||
}
|
}
|
||||||
@ -48,7 +52,7 @@ impl GroupAction for MultiSelectGroupController {
|
|||||||
|
|
||||||
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||||
let mut group_changeset = vec![];
|
let mut group_changeset = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_groups(|group| {
|
||||||
if let Some(changeset) = move_group_row(group, &mut context) {
|
if let Some(changeset) = move_group_row(group, &mut context) {
|
||||||
group_changeset.push(changeset);
|
group_changeset.push(changeset);
|
||||||
}
|
}
|
||||||
@ -79,14 +83,20 @@ pub struct MultiSelectGroupGenerator();
|
|||||||
impl GroupGenerator for MultiSelectGroupGenerator {
|
impl GroupGenerator for MultiSelectGroupGenerator {
|
||||||
type Context = SelectOptionGroupContext;
|
type Context = SelectOptionGroupContext;
|
||||||
type TypeOptionType = MultiSelectTypeOptionPB;
|
type TypeOptionType = MultiSelectTypeOptionPB;
|
||||||
|
|
||||||
fn generate_groups(
|
fn generate_groups(
|
||||||
field_id: &str,
|
field_rev: &FieldRevision,
|
||||||
group_ctx: &Self::Context,
|
group_ctx: &Self::Context,
|
||||||
type_option: &Option<Self::TypeOptionType>,
|
type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroupConfig> {
|
) -> GeneratedGroupContext {
|
||||||
match type_option {
|
let group_configs = match type_option {
|
||||||
None => vec![],
|
None => vec![],
|
||||||
Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),
|
Some(type_option) => generate_select_option_groups(&field_rev.id, group_ctx, &type_option.options),
|
||||||
|
};
|
||||||
|
|
||||||
|
GeneratedGroupContext {
|
||||||
|
no_status_group: Some(make_no_status_group(field_rev)),
|
||||||
|
group_configs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::entities::{GroupChangesetPB, RowPB};
|
use crate::entities::{GroupChangesetPB, RowPB};
|
||||||
use crate::services::cell::insert_select_option_cell;
|
use crate::services::cell::insert_select_option_cell;
|
||||||
use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB};
|
use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB};
|
||||||
use crate::services::group::action::GroupAction;
|
use crate::services::group::action::GroupControllerCustomActions;
|
||||||
|
|
||||||
use crate::services::group::controller::{
|
use crate::services::group::controller::{
|
||||||
GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext,
|
GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext,
|
||||||
@ -9,7 +9,7 @@ use crate::services::group::controller::{
|
|||||||
use crate::services::group::controller_impls::select_option_controller::util::*;
|
use crate::services::group::controller_impls::select_option_controller::util::*;
|
||||||
use crate::services::group::entities::Group;
|
use crate::services::group::entities::Group;
|
||||||
|
|
||||||
use crate::services::group::GeneratedGroupConfig;
|
use crate::services::group::{make_no_status_group, GeneratedGroupContext};
|
||||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
||||||
|
|
||||||
// SingleSelect
|
// SingleSelect
|
||||||
@ -20,25 +20,29 @@ pub type SingleSelectGroupController = GenericGroupController<
|
|||||||
SelectOptionCellDataParser,
|
SelectOptionCellDataParser,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
impl GroupAction for SingleSelectGroupController {
|
impl GroupControllerCustomActions for SingleSelectGroupController {
|
||||||
type CellDataType = SelectOptionCellDataPB;
|
type CellDataType = SelectOptionCellDataPB;
|
||||||
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||||
cell_data.select_options.iter().any(|option| option.id == content)
|
cell_data.select_options.iter().any(|option| option.id == content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
fn add_or_remove_row_in_groups_if_match(
|
||||||
|
&mut self,
|
||||||
|
row_rev: &RowRevision,
|
||||||
|
cell_data: &Self::CellDataType,
|
||||||
|
) -> Vec<GroupChangesetPB> {
|
||||||
let mut changesets = vec![];
|
let mut changesets = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_status_groups(|group| {
|
||||||
if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) {
|
if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row_rev) {
|
||||||
changesets.push(changeset);
|
changesets.push(changeset);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
changesets
|
changesets
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||||
let mut changesets = vec![];
|
let mut changesets = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_status_groups(|group| {
|
||||||
if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) {
|
if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) {
|
||||||
changesets.push(changeset);
|
changesets.push(changeset);
|
||||||
}
|
}
|
||||||
@ -48,7 +52,7 @@ impl GroupAction for SingleSelectGroupController {
|
|||||||
|
|
||||||
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||||
let mut group_changeset = vec![];
|
let mut group_changeset = vec![];
|
||||||
self.group_ctx.iter_mut_all_groups(|group| {
|
self.group_ctx.iter_mut_groups(|group| {
|
||||||
if let Some(changeset) = move_group_row(group, &mut context) {
|
if let Some(changeset) = move_group_row(group, &mut context) {
|
||||||
group_changeset.push(changeset);
|
group_changeset.push(changeset);
|
||||||
}
|
}
|
||||||
@ -80,13 +84,18 @@ impl GroupGenerator for SingleSelectGroupGenerator {
|
|||||||
type Context = SelectOptionGroupContext;
|
type Context = SelectOptionGroupContext;
|
||||||
type TypeOptionType = SingleSelectTypeOptionPB;
|
type TypeOptionType = SingleSelectTypeOptionPB;
|
||||||
fn generate_groups(
|
fn generate_groups(
|
||||||
field_id: &str,
|
field_rev: &FieldRevision,
|
||||||
group_ctx: &Self::Context,
|
group_ctx: &Self::Context,
|
||||||
type_option: &Option<Self::TypeOptionType>,
|
type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroupConfig> {
|
) -> GeneratedGroupContext {
|
||||||
match type_option {
|
let group_configs = match type_option {
|
||||||
None => vec![],
|
None => vec![],
|
||||||
Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),
|
Some(type_option) => generate_select_option_groups(&field_rev.id, group_ctx, &type_option.options),
|
||||||
|
};
|
||||||
|
|
||||||
|
GeneratedGroupContext {
|
||||||
|
no_status_group: Some(make_no_status_group(field_rev)),
|
||||||
|
group_configs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use flowy_grid_data_model::revision::{
|
|||||||
|
|
||||||
pub type SelectOptionGroupContext = GroupContext<SelectOptionGroupConfigurationRevision>;
|
pub type SelectOptionGroupContext = GroupContext<SelectOptionGroupConfigurationRevision>;
|
||||||
|
|
||||||
pub fn add_select_option_row(
|
pub fn add_or_remove_select_option_row(
|
||||||
group: &mut Group,
|
group: &mut Group,
|
||||||
cell_data: &SelectOptionCellDataPB,
|
cell_data: &SelectOptionCellDataPB,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
|
@ -97,7 +97,7 @@ pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurat
|
|||||||
let field_id = field_rev.id.clone();
|
let field_id = field_rev.id.clone();
|
||||||
let field_type_rev = field_rev.ty;
|
let field_type_rev = field_rev.ty;
|
||||||
let field_type: FieldType = field_rev.ty.into();
|
let field_type: FieldType = field_rev.ty.into();
|
||||||
let mut group_configuration_rev = match field_type {
|
match field_type {
|
||||||
FieldType::RichText => {
|
FieldType::RichText => {
|
||||||
GroupConfigurationRevision::new(field_id, field_type_rev, TextGroupConfigurationRevision::default())
|
GroupConfigurationRevision::new(field_id, field_type_rev, TextGroupConfigurationRevision::default())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -130,11 +130,7 @@ pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurat
|
|||||||
FieldType::URL => {
|
FieldType::URL => {
|
||||||
GroupConfigurationRevision::new(field_id, field_type_rev, UrlGroupConfigurationRevision::default()).unwrap()
|
GroupConfigurationRevision::new(field_id, field_type_rev, UrlGroupConfigurationRevision::default()).unwrap()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Append the no `status` group
|
|
||||||
group_configuration_rev.groups.push(make_no_status_group(field_rev));
|
|
||||||
group_configuration_rev
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_no_status_group(field_rev: &FieldRevision) -> GroupRevision {
|
pub fn make_no_status_group(field_rev: &FieldRevision) -> GroupRevision {
|
||||||
|
@ -42,7 +42,7 @@ impl TextEditorCloudService for BlockHttpCloudService {
|
|||||||
|
|
||||||
pub async fn create_document_request(token: &str, params: CreateTextBlockParams, url: &str) -> Result<(), FlowyError> {
|
pub async fn create_document_request(token: &str, params: CreateTextBlockParams, url: &str) -> Result<(), FlowyError> {
|
||||||
let _ = request_builder()
|
let _ = request_builder()
|
||||||
.post(&url.to_owned())
|
.post(url)
|
||||||
.header(HEADER_TOKEN, token)
|
.header(HEADER_TOKEN, token)
|
||||||
.protobuf(params)?
|
.protobuf(params)?
|
||||||
.send()
|
.send()
|
||||||
@ -56,7 +56,7 @@ pub async fn read_document_request(
|
|||||||
url: &str,
|
url: &str,
|
||||||
) -> Result<Option<DocumentPB>, FlowyError> {
|
) -> Result<Option<DocumentPB>, FlowyError> {
|
||||||
let doc = request_builder()
|
let doc = request_builder()
|
||||||
.get(&url.to_owned())
|
.get(url)
|
||||||
.header(HEADER_TOKEN, token)
|
.header(HEADER_TOKEN, token)
|
||||||
.protobuf(params)?
|
.protobuf(params)?
|
||||||
.option_response()
|
.option_response()
|
||||||
@ -67,7 +67,7 @@ pub async fn read_document_request(
|
|||||||
|
|
||||||
pub async fn reset_doc_request(token: &str, params: ResetTextBlockParams, url: &str) -> Result<(), FlowyError> {
|
pub async fn reset_doc_request(token: &str, params: ResetTextBlockParams, url: &str) -> Result<(), FlowyError> {
|
||||||
let _ = request_builder()
|
let _ = request_builder()
|
||||||
.patch(&url.to_owned())
|
.patch(url)
|
||||||
.header(HEADER_TOKEN, token)
|
.header(HEADER_TOKEN, token)
|
||||||
.protobuf(params)?
|
.protobuf(params)?
|
||||||
.send()
|
.send()
|
||||||
|
@ -66,35 +66,23 @@ impl UserCloudService for UserHttpCloudService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn user_sign_up_request(params: SignUpParams, url: &str) -> Result<SignUpResponse, ServerError> {
|
pub async fn user_sign_up_request(params: SignUpParams, url: &str) -> Result<SignUpResponse, ServerError> {
|
||||||
let response = request_builder()
|
let response = request_builder().post(url).protobuf(params)?.response().await?;
|
||||||
.post(&url.to_owned())
|
|
||||||
.protobuf(params)?
|
|
||||||
.response()
|
|
||||||
.await?;
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn user_sign_in_request(params: SignInParams, url: &str) -> Result<SignInResponse, ServerError> {
|
pub async fn user_sign_in_request(params: SignInParams, url: &str) -> Result<SignInResponse, ServerError> {
|
||||||
let response = request_builder()
|
let response = request_builder().post(url).protobuf(params)?.response().await?;
|
||||||
.post(&url.to_owned())
|
|
||||||
.protobuf(params)?
|
|
||||||
.response()
|
|
||||||
.await?;
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn user_sign_out_request(token: &str, url: &str) -> Result<(), ServerError> {
|
pub async fn user_sign_out_request(token: &str, url: &str) -> Result<(), ServerError> {
|
||||||
let _ = request_builder()
|
let _ = request_builder().delete(url).header(HEADER_TOKEN, token).send().await?;
|
||||||
.delete(&url.to_owned())
|
|
||||||
.header(HEADER_TOKEN, token)
|
|
||||||
.send()
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_user_profile_request(token: &str, url: &str) -> Result<UserProfilePB, ServerError> {
|
pub async fn get_user_profile_request(token: &str, url: &str) -> Result<UserProfilePB, ServerError> {
|
||||||
let user_profile = request_builder()
|
let user_profile = request_builder()
|
||||||
.get(&url.to_owned())
|
.get(url)
|
||||||
.header(HEADER_TOKEN, token)
|
.header(HEADER_TOKEN, token)
|
||||||
.response()
|
.response()
|
||||||
.await?;
|
.await?;
|
||||||
@ -107,7 +95,7 @@ pub async fn update_user_profile_request(
|
|||||||
url: &str,
|
url: &str,
|
||||||
) -> Result<(), ServerError> {
|
) -> Result<(), ServerError> {
|
||||||
let _ = request_builder()
|
let _ = request_builder()
|
||||||
.patch(&url.to_owned())
|
.patch(url)
|
||||||
.header(HEADER_TOKEN, token)
|
.header(HEADER_TOKEN, token)
|
||||||
.protobuf(params)?
|
.protobuf(params)?
|
||||||
.send()
|
.send()
|
||||||
|
@ -164,7 +164,7 @@ impl RevisionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn next_sync_revision(&self) -> FlowyResult<Option<Revision>> {
|
pub async fn next_sync_revision(&self) -> FlowyResult<Option<Revision>> {
|
||||||
Ok(self.rev_persistence.next_sync_revision().await?)
|
self.rev_persistence.next_sync_revision().await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_revision(&self, rev_id: i64) -> Option<Revision> {
|
pub async fn get_revision(&self, rev_id: i64) -> Option<Revision> {
|
||||||
|
@ -130,7 +130,6 @@ impl RevisionPersistence {
|
|||||||
#[tracing::instrument(level = "trace", skip(self, revisions), err)]
|
#[tracing::instrument(level = "trace", skip(self, revisions), err)]
|
||||||
pub(crate) async fn reset(&self, revisions: Vec<Revision>) -> FlowyResult<()> {
|
pub(crate) async fn reset(&self, revisions: Vec<Revision>) -> FlowyResult<()> {
|
||||||
let records = revisions
|
let records = revisions
|
||||||
.to_vec()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|revision| RevisionRecord {
|
.map(|revision| RevisionRecord {
|
||||||
revision,
|
revision,
|
||||||
|
@ -114,11 +114,10 @@ fn format_event_message<S: Subscriber + for<'a> tracing_subscriber::registry::Lo
|
|||||||
let mut message = event_visitor
|
let mut message = event_visitor
|
||||||
.values()
|
.values()
|
||||||
.get("message")
|
.get("message")
|
||||||
.map(|v| match v {
|
.and_then(|v| match v {
|
||||||
Value::String(s) => Some(s.as_str()),
|
Value::String(s) => Some(s.as_str()),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.unwrap_or_else(|| event.metadata().target())
|
.unwrap_or_else(|| event.metadata().target())
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
|
@ -73,4 +73,8 @@ impl CellRevision {
|
|||||||
pub fn new(data: String) -> Self {
|
pub fn new(data: String) -> Self {
|
||||||
Self { data }
|
Self { data }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.data.is_empty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user