|
@@ -4,7 +4,7 @@ use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOper
|
|
|
use crate::services::field::type_options::util::get_cell_data;
|
|
|
use crate::services::field::{
|
|
|
make_selected_select_options, BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionCellDataPB,
|
|
|
- SelectOptionIds, SelectOptionOperation, SelectOptionPB, TypeOptionBuilder, SELECTION_IDS_SEPARATOR,
|
|
|
+ SelectOptionIds, SelectOptionOperation, SelectOptionPB, TypeOptionBuilder,
|
|
|
};
|
|
|
use bytes::Bytes;
|
|
|
use flowy_derive::ProtoBuf;
|
|
@@ -61,29 +61,32 @@ impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSele
|
|
|
cell_rev: Option<CellRevision>,
|
|
|
) -> Result<String, FlowyError> {
|
|
|
let content_changeset = changeset.try_into_inner()?;
|
|
|
+
|
|
|
+ let insert_option_ids = content_changeset
|
|
|
+ .insert_option_ids
|
|
|
+ .into_iter()
|
|
|
+ .filter(|insert_option_id| self.options.iter().any(|option| &option.id == insert_option_id))
|
|
|
+ .collect::<Vec<String>>();
|
|
|
+
|
|
|
let new_cell_data: String;
|
|
|
match cell_rev {
|
|
|
None => {
|
|
|
- new_cell_data = content_changeset.insert_option_id.unwrap_or_else(|| "".to_owned());
|
|
|
+ new_cell_data = SelectOptionIds::from(insert_option_ids).to_string();
|
|
|
}
|
|
|
Some(cell_rev) => {
|
|
|
let cell_data = get_cell_data(&cell_rev);
|
|
|
let mut select_ids: SelectOptionIds = cell_data.into();
|
|
|
- if let Some(insert_option_id) = content_changeset.insert_option_id {
|
|
|
- tracing::trace!("Insert multi select option: {}", &insert_option_id);
|
|
|
- if select_ids.contains(&insert_option_id) {
|
|
|
- select_ids.retain(|id| id != &insert_option_id);
|
|
|
- } else {
|
|
|
+ for insert_option_id in insert_option_ids {
|
|
|
+ if !select_ids.contains(&insert_option_id) {
|
|
|
select_ids.push(insert_option_id);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if let Some(delete_option_id) = content_changeset.delete_option_id {
|
|
|
- tracing::trace!("Delete multi select option: {}", &delete_option_id);
|
|
|
+ for delete_option_id in content_changeset.delete_option_ids {
|
|
|
select_ids.retain(|id| id != &delete_option_id);
|
|
|
}
|
|
|
|
|
|
- new_cell_data = select_ids.join(SELECTION_IDS_SEPARATOR);
|
|
|
+ new_cell_data = select_ids.to_string();
|
|
|
tracing::trace!("Multi select cell data: {}", &new_cell_data);
|
|
|
}
|
|
|
}
|
|
@@ -114,22 +117,55 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder {
|
|
|
}
|
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
|
- use crate::entities::FieldType;
|
|
|
use crate::services::cell::CellDataOperation;
|
|
|
use crate::services::field::type_options::selection_type_option::*;
|
|
|
use crate::services::field::FieldBuilder;
|
|
|
use crate::services::field::{MultiSelectTypeOptionBuilder, MultiSelectTypeOptionPB};
|
|
|
- use flowy_grid_data_model::revision::FieldRevision;
|
|
|
|
|
|
#[test]
|
|
|
- fn multi_select_test() {
|
|
|
- let google_option = SelectOptionPB::new("Google");
|
|
|
- let facebook_option = SelectOptionPB::new("Facebook");
|
|
|
- let twitter_option = SelectOptionPB::new("Twitter");
|
|
|
+ fn multi_select_insert_multi_option_test() {
|
|
|
+ let google = SelectOptionPB::new("Google");
|
|
|
+ let facebook = SelectOptionPB::new("Facebook");
|
|
|
let multi_select = MultiSelectTypeOptionBuilder::default()
|
|
|
- .add_option(google_option.clone())
|
|
|
- .add_option(facebook_option.clone())
|
|
|
- .add_option(twitter_option);
|
|
|
+ .add_option(google.clone())
|
|
|
+ .add_option(facebook.clone());
|
|
|
+
|
|
|
+ let field_rev = FieldBuilder::new(multi_select).name("Platform").build();
|
|
|
+ let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
|
|
+ let option_ids = vec![google.id, facebook.id];
|
|
|
+ let data = SelectOptionCellChangeset::from_insert_options(option_ids.clone()).to_str();
|
|
|
+ let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
|
|
+
|
|
|
+ assert_eq!(&*select_option_ids, &option_ids);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn multi_select_unselect_multi_option_test() {
|
|
|
+ let google = SelectOptionPB::new("Google");
|
|
|
+ let facebook = SelectOptionPB::new("Facebook");
|
|
|
+ let multi_select = MultiSelectTypeOptionBuilder::default()
|
|
|
+ .add_option(google.clone())
|
|
|
+ .add_option(facebook.clone());
|
|
|
+
|
|
|
+ let field_rev = FieldBuilder::new(multi_select).name("Platform").build();
|
|
|
+ let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
|
|
+ let option_ids = vec![google.id, facebook.id];
|
|
|
+
|
|
|
+ // insert
|
|
|
+ let data = SelectOptionCellChangeset::from_insert_options(option_ids.clone()).to_str();
|
|
|
+ let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
|
|
+ assert_eq!(&*select_option_ids, &option_ids);
|
|
|
+
|
|
|
+ // delete
|
|
|
+ let data = SelectOptionCellChangeset::from_delete_options(option_ids).to_str();
|
|
|
+ let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
|
|
+ assert!(select_option_ids.is_empty());
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn multi_select_insert_single_option_test() {
|
|
|
+ let google = SelectOptionPB::new("Google");
|
|
|
+ let multi_select = MultiSelectTypeOptionBuilder::default().add_option(google.clone());
|
|
|
|
|
|
let field_rev = FieldBuilder::new(multi_select)
|
|
|
.name("Platform")
|
|
@@ -137,52 +173,55 @@ mod tests {
|
|
|
.build();
|
|
|
|
|
|
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
|
|
+ let data = SelectOptionCellChangeset::from_insert_option_id(&google.id).to_str();
|
|
|
+ let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
|
|
+ assert_eq!(cell_option_ids, google.id);
|
|
|
+ }
|
|
|
|
|
|
- let option_ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
|
|
|
- let data = SelectOptionCellChangeset::from_insert(&option_ids).to_str();
|
|
|
- let cell_data = type_option.apply_changeset(data.into(), None).unwrap();
|
|
|
- assert_multi_select_options(
|
|
|
- cell_data,
|
|
|
- &type_option,
|
|
|
- &field_rev,
|
|
|
- vec![google_option.clone(), facebook_option],
|
|
|
- );
|
|
|
-
|
|
|
- let data = SelectOptionCellChangeset::from_insert(&google_option.id).to_str();
|
|
|
- let cell_data = type_option.apply_changeset(data.into(), None).unwrap();
|
|
|
- assert_multi_select_options(cell_data, &type_option, &field_rev, vec![google_option]);
|
|
|
-
|
|
|
- // Invalid option id
|
|
|
- let cell_data = type_option
|
|
|
- .apply_changeset(SelectOptionCellChangeset::from_insert("").to_str().into(), None)
|
|
|
- .unwrap();
|
|
|
- assert_multi_select_options(cell_data, &type_option, &field_rev, vec![]);
|
|
|
-
|
|
|
- // Invalid option id
|
|
|
- let cell_data = type_option
|
|
|
- .apply_changeset(SelectOptionCellChangeset::from_insert("123,456").to_str().into(), None)
|
|
|
- .unwrap();
|
|
|
- assert_multi_select_options(cell_data, &type_option, &field_rev, vec![]);
|
|
|
-
|
|
|
- // Invalid changeset
|
|
|
- assert!(type_option.apply_changeset("123".to_owned().into(), None).is_err());
|
|
|
+ #[test]
|
|
|
+ fn multi_select_insert_non_exist_option_test() {
|
|
|
+ let google = SelectOptionPB::new("Google");
|
|
|
+ let multi_select = MultiSelectTypeOptionBuilder::default();
|
|
|
+ let field_rev = FieldBuilder::new(multi_select)
|
|
|
+ .name("Platform")
|
|
|
+ .visibility(true)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
|
|
+ let data = SelectOptionCellChangeset::from_insert_option_id(&google.id).to_str();
|
|
|
+ let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
|
|
+ assert!(cell_option_ids.is_empty());
|
|
|
}
|
|
|
|
|
|
- fn assert_multi_select_options(
|
|
|
- cell_data: String,
|
|
|
- type_option: &MultiSelectTypeOptionPB,
|
|
|
- field_rev: &FieldRevision,
|
|
|
- expected: Vec<SelectOptionPB>,
|
|
|
- ) {
|
|
|
- let field_type: FieldType = field_rev.ty.into();
|
|
|
- assert_eq!(
|
|
|
- expected,
|
|
|
- type_option
|
|
|
- .decode_cell_data(cell_data.into(), &field_type, field_rev)
|
|
|
- .unwrap()
|
|
|
- .parser::<SelectOptionCellDataParser>()
|
|
|
- .unwrap()
|
|
|
- .select_options,
|
|
|
- );
|
|
|
+ #[test]
|
|
|
+ fn multi_select_insert_invalid_option_id_test() {
|
|
|
+ let google = SelectOptionPB::new("Google");
|
|
|
+ let multi_select = MultiSelectTypeOptionBuilder::default().add_option(google);
|
|
|
+
|
|
|
+ let field_rev = FieldBuilder::new(multi_select)
|
|
|
+ .name("Platform")
|
|
|
+ .visibility(true)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
|
|
+
|
|
|
+ // empty option id string
|
|
|
+ let data = SelectOptionCellChangeset::from_insert_option_id("").to_str();
|
|
|
+ let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
|
|
+ assert_eq!(cell_option_ids, "");
|
|
|
+
|
|
|
+ let data = SelectOptionCellChangeset::from_insert_option_id("123,456").to_str();
|
|
|
+ let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
|
|
+ assert_eq!(cell_option_ids, "");
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn multi_select_invalid_changeset_data_test() {
|
|
|
+ let multi_select = MultiSelectTypeOptionBuilder::default();
|
|
|
+ let field_rev = FieldBuilder::new(multi_select).name("Platform").build();
|
|
|
+ let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
|
|
+
|
|
|
+ // The type of the changeset should be SelectOptionCellChangeset
|
|
|
+ assert!(type_option.apply_changeset("123".to_owned().into(), None).is_err());
|
|
|
}
|
|
|
}
|