grid_editor.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. #![allow(clippy::all)]
  2. #![allow(dead_code)]
  3. #![allow(unused_imports)]
  4. use crate::grid::block_test::util::GridRowTestBuilder;
  5. use bytes::Bytes;
  6. use flowy_error::FlowyResult;
  7. use flowy_grid::entities::*;
  8. use flowy_grid::services::field::SelectOptionPB;
  9. use flowy_grid::services::field::*;
  10. use flowy_grid::services::grid_editor::{GridRevisionEditor, GridRevisionSerde};
  11. use flowy_grid::services::row::{CreateRowRevisionPayload, RowRevisionBuilder};
  12. use flowy_grid::services::setting::GridSettingChangesetBuilder;
  13. use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS;
  14. use flowy_sync::client_grid::GridBuilder;
  15. use flowy_test::helper::ViewTest;
  16. use flowy_test::FlowySDKTest;
  17. use grid_rev_model::*;
  18. use std::collections::HashMap;
  19. use std::sync::Arc;
  20. use std::time::Duration;
  21. use strum::EnumCount;
  22. use strum::IntoEnumIterator;
  23. use tokio::time::sleep;
  24. pub struct GridEditorTest {
  25. pub sdk: FlowySDKTest,
  26. pub grid_id: String,
  27. pub editor: Arc<GridRevisionEditor>,
  28. pub field_revs: Vec<Arc<FieldRevision>>,
  29. pub block_meta_revs: Vec<Arc<GridBlockMetaRevision>>,
  30. pub row_revs: Vec<Arc<RowRevision>>,
  31. pub field_count: usize,
  32. pub row_order_by_row_id: HashMap<String, RowPB>,
  33. }
  34. impl GridEditorTest {
  35. pub async fn new_table() -> Self {
  36. Self::new(GridLayout::Table).await
  37. }
  38. pub async fn new_board() -> Self {
  39. Self::new(GridLayout::Board).await
  40. }
  41. pub async fn new(layout: GridLayout) -> Self {
  42. let sdk = FlowySDKTest::default();
  43. let _ = sdk.init_user().await;
  44. let test = match layout {
  45. GridLayout::Table => {
  46. let build_context = make_test_grid();
  47. let view_data: Bytes = build_context.into();
  48. ViewTest::new_grid_view(&sdk, view_data.to_vec()).await
  49. }
  50. GridLayout::Board => {
  51. let build_context = make_test_board();
  52. let view_data: Bytes = build_context.into();
  53. ViewTest::new_board_view(&sdk, view_data.to_vec()).await
  54. }
  55. };
  56. let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
  57. let field_revs = editor.get_field_revs(None).await.unwrap();
  58. let block_meta_revs = editor.get_block_meta_revs().await.unwrap();
  59. let row_revs = editor.get_blocks(None).await.unwrap().pop().unwrap().row_revs;
  60. assert_eq!(block_meta_revs.len(), 1);
  61. // It seems like you should add the field in the make_test_grid() function.
  62. // Because we assert the initialize count of the fields is equal to FieldType::COUNT.
  63. assert_eq!(field_revs.len(), FieldType::COUNT);
  64. let grid_id = test.view.id;
  65. Self {
  66. sdk,
  67. grid_id,
  68. editor,
  69. field_revs,
  70. block_meta_revs,
  71. row_revs,
  72. field_count: FieldType::COUNT,
  73. row_order_by_row_id: HashMap::default(),
  74. }
  75. }
  76. pub async fn get_row_revs(&self) -> Vec<Arc<RowRevision>> {
  77. self.editor.get_blocks(None).await.unwrap().pop().unwrap().row_revs
  78. }
  79. pub async fn grid_filters(&self) -> Vec<FilterPB> {
  80. self.editor.get_all_filters().await.unwrap()
  81. }
  82. pub fn get_field_rev(&self, field_id: &str, field_type: FieldType) -> &Arc<FieldRevision> {
  83. self.field_revs
  84. .iter()
  85. .filter(|field_rev| {
  86. let t_field_type: FieldType = field_rev.ty.into();
  87. field_rev.id == field_id && t_field_type == field_type
  88. })
  89. .collect::<Vec<_>>()
  90. .pop()
  91. .unwrap()
  92. }
  93. pub fn get_first_field_rev(&self, field_type: FieldType) -> &Arc<FieldRevision> {
  94. self.field_revs
  95. .iter()
  96. .filter(|field_rev| {
  97. let t_field_type: FieldType = field_rev.ty.into();
  98. t_field_type == field_type
  99. })
  100. .collect::<Vec<_>>()
  101. .pop()
  102. .unwrap()
  103. }
  104. pub fn get_multi_select_type_option(&self, field_id: &str) -> Vec<SelectOptionPB> {
  105. let field_type = FieldType::MultiSelect;
  106. let field_rev = self.get_field_rev(field_id, field_type.clone());
  107. let type_option = field_rev
  108. .get_type_option::<MultiSelectTypeOptionPB>(field_type.into())
  109. .unwrap();
  110. type_option.options
  111. }
  112. pub fn get_single_select_type_option(&self, field_id: &str) -> SingleSelectTypeOptionPB {
  113. let field_type = FieldType::SingleSelect;
  114. let field_rev = self.get_field_rev(field_id, field_type.clone());
  115. let type_option = field_rev
  116. .get_type_option::<SingleSelectTypeOptionPB>(field_type.into())
  117. .unwrap();
  118. type_option
  119. }
  120. pub fn get_checklist_type_option(&self, field_id: &str) -> ChecklistTypeOptionPB {
  121. let field_type = FieldType::Checklist;
  122. let field_rev = self.get_field_rev(field_id, field_type.clone());
  123. let type_option = field_rev
  124. .get_type_option::<ChecklistTypeOptionPB>(field_type.into())
  125. .unwrap();
  126. type_option
  127. }
  128. pub fn get_checkbox_type_option(&self, field_id: &str) -> CheckboxTypeOptionPB {
  129. let field_type = FieldType::Checkbox;
  130. let field_rev = self.get_field_rev(field_id, field_type.clone());
  131. let type_option = field_rev
  132. .get_type_option::<CheckboxTypeOptionPB>(field_type.into())
  133. .unwrap();
  134. type_option
  135. }
  136. pub fn block_id(&self) -> &str {
  137. &self.block_meta_revs.last().unwrap().block_id
  138. }
  139. }
  140. pub const GOOGLE: &str = "Google";
  141. pub const FACEBOOK: &str = "Facebook";
  142. pub const TWITTER: &str = "Twitter";
  143. pub const COMPLETED: &str = "Completed";
  144. pub const PLANNED: &str = "Planned";
  145. pub const PAUSED: &str = "Paused";
  146. pub const FIRST_THING: &str = "Wake up at 6:00 am";
  147. pub const SECOND_THING: &str = "Get some coffee";
  148. pub const THIRD_THING: &str = "Start working";
  149. // This grid is assumed to contain all the Fields.
  150. fn make_test_grid() -> BuildGridContext {
  151. let mut grid_builder = GridBuilder::new();
  152. // Iterate through the FieldType to create the corresponding Field.
  153. for field_type in FieldType::iter() {
  154. let field_type: FieldType = field_type;
  155. // The
  156. match field_type {
  157. FieldType::RichText => {
  158. let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
  159. .name("Name")
  160. .visibility(true)
  161. .primary(true)
  162. .build();
  163. grid_builder.add_field(text_field);
  164. }
  165. FieldType::Number => {
  166. // Number
  167. let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
  168. let number_field = FieldBuilder::new(number).name("Price").visibility(true).build();
  169. grid_builder.add_field(number_field);
  170. }
  171. FieldType::DateTime => {
  172. // Date
  173. let date = DateTypeOptionBuilder::default()
  174. .date_format(DateFormat::US)
  175. .time_format(TimeFormat::TwentyFourHour);
  176. let date_field = FieldBuilder::new(date).name("Time").visibility(true).build();
  177. grid_builder.add_field(date_field);
  178. }
  179. FieldType::SingleSelect => {
  180. // Single Select
  181. let single_select = SingleSelectTypeOptionBuilder::default()
  182. .add_option(SelectOptionPB::new(COMPLETED))
  183. .add_option(SelectOptionPB::new(PLANNED))
  184. .add_option(SelectOptionPB::new(PAUSED));
  185. let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
  186. grid_builder.add_field(single_select_field);
  187. }
  188. FieldType::MultiSelect => {
  189. // MultiSelect
  190. let multi_select = MultiSelectTypeOptionBuilder::default()
  191. .add_option(SelectOptionPB::new(GOOGLE))
  192. .add_option(SelectOptionPB::new(FACEBOOK))
  193. .add_option(SelectOptionPB::new(TWITTER));
  194. let multi_select_field = FieldBuilder::new(multi_select)
  195. .name("Platform")
  196. .visibility(true)
  197. .build();
  198. grid_builder.add_field(multi_select_field);
  199. }
  200. FieldType::Checkbox => {
  201. // Checkbox
  202. let checkbox = CheckboxTypeOptionBuilder::default();
  203. let checkbox_field = FieldBuilder::new(checkbox).name("is urgent").visibility(true).build();
  204. grid_builder.add_field(checkbox_field);
  205. }
  206. FieldType::URL => {
  207. // URL
  208. let url = URLTypeOptionBuilder::default();
  209. let url_field = FieldBuilder::new(url).name("link").visibility(true).build();
  210. grid_builder.add_field(url_field);
  211. }
  212. FieldType::Checklist => {
  213. let checklist = ChecklistTypeOptionBuilder::default()
  214. .add_option(SelectOptionPB::new(FIRST_THING))
  215. .add_option(SelectOptionPB::new(SECOND_THING))
  216. .add_option(SelectOptionPB::new(THIRD_THING));
  217. let checklist_field = FieldBuilder::new(checklist).name("TODO").visibility(true).build();
  218. grid_builder.add_field(checklist_field);
  219. }
  220. }
  221. }
  222. // We have many assumptions base on the number of the rows, so do not change the number of the loop.
  223. for i in 0..5 {
  224. let block_id = grid_builder.block_id().to_owned();
  225. let field_revs = grid_builder.field_revs();
  226. let mut row_builder = GridRowTestBuilder::new(&block_id, field_revs);
  227. match i {
  228. 0 => {
  229. for field_type in FieldType::iter() {
  230. match field_type {
  231. FieldType::RichText => row_builder.insert_text_cell("A"),
  232. FieldType::Number => row_builder.insert_number_cell("1"),
  233. FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
  234. FieldType::MultiSelect => row_builder
  235. .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]),
  236. FieldType::Checklist => row_builder.insert_checklist_cell(|options| options),
  237. FieldType::Checkbox => row_builder.insert_checkbox_cell("true"),
  238. _ => "".to_owned(),
  239. };
  240. }
  241. }
  242. 1 => {
  243. for field_type in FieldType::iter() {
  244. match field_type {
  245. FieldType::RichText => row_builder.insert_text_cell(""),
  246. FieldType::Number => row_builder.insert_number_cell("2"),
  247. FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
  248. FieldType::MultiSelect => row_builder
  249. .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]),
  250. FieldType::Checkbox => row_builder.insert_checkbox_cell("true"),
  251. _ => "".to_owned(),
  252. };
  253. }
  254. }
  255. 2 => {
  256. for field_type in FieldType::iter() {
  257. match field_type {
  258. FieldType::RichText => row_builder.insert_text_cell("C"),
  259. FieldType::Number => row_builder.insert_number_cell("3"),
  260. FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
  261. FieldType::SingleSelect => {
  262. row_builder.insert_single_select_cell(|mut options| options.remove(0))
  263. }
  264. FieldType::MultiSelect => {
  265. row_builder.insert_multi_select_cell(|mut options| vec![options.remove(1)])
  266. }
  267. FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
  268. _ => "".to_owned(),
  269. };
  270. }
  271. }
  272. 3 => {
  273. for field_type in FieldType::iter() {
  274. match field_type {
  275. FieldType::RichText => row_builder.insert_text_cell("DA"),
  276. FieldType::Number => row_builder.insert_number_cell("4"),
  277. FieldType::DateTime => row_builder.insert_date_cell("1668704685"),
  278. FieldType::SingleSelect => {
  279. row_builder.insert_single_select_cell(|mut options| options.remove(0))
  280. }
  281. FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
  282. _ => "".to_owned(),
  283. };
  284. }
  285. }
  286. 4 => {
  287. for field_type in FieldType::iter() {
  288. match field_type {
  289. FieldType::RichText => row_builder.insert_text_cell("AE"),
  290. FieldType::Number => row_builder.insert_number_cell(""),
  291. FieldType::DateTime => row_builder.insert_date_cell("1668359085"),
  292. FieldType::SingleSelect => {
  293. row_builder.insert_single_select_cell(|mut options| options.remove(1))
  294. }
  295. FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
  296. _ => "".to_owned(),
  297. };
  298. }
  299. }
  300. _ => {}
  301. }
  302. let row_rev = row_builder.build();
  303. grid_builder.add_row(row_rev);
  304. }
  305. grid_builder.build()
  306. }
  307. fn make_test_board() -> BuildGridContext {
  308. let mut grid_builder = GridBuilder::new();
  309. // Iterate through the FieldType to create the corresponding Field.
  310. for field_type in FieldType::iter() {
  311. let field_type: FieldType = field_type;
  312. // The
  313. match field_type {
  314. FieldType::RichText => {
  315. let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
  316. .name("Name")
  317. .visibility(true)
  318. .primary(true)
  319. .build();
  320. grid_builder.add_field(text_field);
  321. }
  322. FieldType::Number => {
  323. // Number
  324. let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
  325. let number_field = FieldBuilder::new(number).name("Price").visibility(true).build();
  326. grid_builder.add_field(number_field);
  327. }
  328. FieldType::DateTime => {
  329. // Date
  330. let date = DateTypeOptionBuilder::default()
  331. .date_format(DateFormat::US)
  332. .time_format(TimeFormat::TwentyFourHour);
  333. let date_field = FieldBuilder::new(date).name("Time").visibility(true).build();
  334. grid_builder.add_field(date_field);
  335. }
  336. FieldType::SingleSelect => {
  337. // Single Select
  338. let single_select = SingleSelectTypeOptionBuilder::default()
  339. .add_option(SelectOptionPB::new(COMPLETED))
  340. .add_option(SelectOptionPB::new(PLANNED))
  341. .add_option(SelectOptionPB::new(PAUSED));
  342. let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
  343. grid_builder.add_field(single_select_field);
  344. }
  345. FieldType::MultiSelect => {
  346. // MultiSelect
  347. let multi_select = MultiSelectTypeOptionBuilder::default()
  348. .add_option(SelectOptionPB::new(GOOGLE))
  349. .add_option(SelectOptionPB::new(FACEBOOK))
  350. .add_option(SelectOptionPB::new(TWITTER));
  351. let multi_select_field = FieldBuilder::new(multi_select)
  352. .name("Platform")
  353. .visibility(true)
  354. .build();
  355. grid_builder.add_field(multi_select_field);
  356. }
  357. FieldType::Checkbox => {
  358. // Checkbox
  359. let checkbox = CheckboxTypeOptionBuilder::default();
  360. let checkbox_field = FieldBuilder::new(checkbox).name("is urgent").visibility(true).build();
  361. grid_builder.add_field(checkbox_field);
  362. }
  363. FieldType::URL => {
  364. // URL
  365. let url = URLTypeOptionBuilder::default();
  366. let url_field = FieldBuilder::new(url).name("link").visibility(true).build();
  367. grid_builder.add_field(url_field);
  368. }
  369. FieldType::Checklist => {}
  370. }
  371. }
  372. // We have many assumptions base on the number of the rows, so do not change the number of the loop.
  373. for i in 0..5 {
  374. let block_id = grid_builder.block_id().to_owned();
  375. let field_revs = grid_builder.field_revs();
  376. let mut row_builder = GridRowTestBuilder::new(&block_id, field_revs);
  377. match i {
  378. 0 => {
  379. for field_type in FieldType::iter() {
  380. match field_type {
  381. FieldType::RichText => row_builder.insert_text_cell("A"),
  382. FieldType::Number => row_builder.insert_number_cell("1"),
  383. FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
  384. FieldType::SingleSelect => {
  385. row_builder.insert_single_select_cell(|mut options| options.remove(0))
  386. }
  387. FieldType::MultiSelect => row_builder
  388. .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]),
  389. FieldType::Checkbox => row_builder.insert_checkbox_cell("true"),
  390. _ => "".to_owned(),
  391. };
  392. }
  393. }
  394. 1 => {
  395. for field_type in FieldType::iter() {
  396. match field_type {
  397. FieldType::RichText => row_builder.insert_text_cell("B"),
  398. FieldType::Number => row_builder.insert_number_cell("2"),
  399. FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
  400. FieldType::SingleSelect => {
  401. row_builder.insert_single_select_cell(|mut options| options.remove(0))
  402. }
  403. FieldType::MultiSelect => row_builder
  404. .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]),
  405. FieldType::Checkbox => row_builder.insert_checkbox_cell("true"),
  406. _ => "".to_owned(),
  407. };
  408. }
  409. }
  410. 2 => {
  411. for field_type in FieldType::iter() {
  412. match field_type {
  413. FieldType::RichText => row_builder.insert_text_cell("C"),
  414. FieldType::Number => row_builder.insert_number_cell("3"),
  415. FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
  416. FieldType::SingleSelect => {
  417. row_builder.insert_single_select_cell(|mut options| options.remove(1))
  418. }
  419. FieldType::MultiSelect => {
  420. row_builder.insert_multi_select_cell(|mut options| vec![options.remove(0)])
  421. }
  422. FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
  423. _ => "".to_owned(),
  424. };
  425. }
  426. }
  427. 3 => {
  428. for field_type in FieldType::iter() {
  429. match field_type {
  430. FieldType::RichText => row_builder.insert_text_cell("DA"),
  431. FieldType::Number => row_builder.insert_number_cell("4"),
  432. FieldType::DateTime => row_builder.insert_date_cell("1668704685"),
  433. FieldType::SingleSelect => {
  434. row_builder.insert_single_select_cell(|mut options| options.remove(1))
  435. }
  436. FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
  437. _ => "".to_owned(),
  438. };
  439. }
  440. }
  441. 4 => {
  442. for field_type in FieldType::iter() {
  443. match field_type {
  444. FieldType::RichText => row_builder.insert_text_cell("AE"),
  445. FieldType::Number => row_builder.insert_number_cell(""),
  446. FieldType::DateTime => row_builder.insert_date_cell("1668359085"),
  447. FieldType::SingleSelect => {
  448. row_builder.insert_single_select_cell(|mut options| options.remove(2))
  449. }
  450. FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
  451. _ => "".to_owned(),
  452. };
  453. }
  454. }
  455. _ => {}
  456. }
  457. let row_rev = row_builder.build();
  458. grid_builder.add_row(row_rev);
  459. }
  460. grid_builder.build()
  461. }