database_editor.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. use std::collections::HashMap;
  2. use std::sync::Arc;
  3. use collab_database::database::{gen_database_view_id, timestamp};
  4. use collab_database::fields::Field;
  5. use collab_database::rows::{CreateRowParams, Row, RowId};
  6. use strum::EnumCount;
  7. use flowy_database2::entities::{FieldType, FilterPB, RowPB, SelectOptionPB};
  8. use flowy_database2::services::cell::{CellBuilder, ToCellChangeset};
  9. use flowy_database2::services::database::DatabaseEditor;
  10. use flowy_database2::services::field::checklist_type_option::{
  11. ChecklistCellChangeset, ChecklistTypeOption,
  12. };
  13. use flowy_database2::services::field::{
  14. CheckboxTypeOption, DateCellChangeset, MultiSelectTypeOption, SelectOption,
  15. SelectOptionCellChangeset, SingleSelectTypeOption,
  16. };
  17. use flowy_database2::services::share::csv::{CSVFormat, ImportResult};
  18. use flowy_error::FlowyResult;
  19. use flowy_test::folder_event::ViewTest;
  20. use flowy_test::FlowyCoreTest;
  21. use crate::database::mock_data::{
  22. make_no_date_test_grid, make_test_board, make_test_calendar, make_test_grid,
  23. };
  24. pub struct DatabaseEditorTest {
  25. pub sdk: FlowyCoreTest,
  26. pub app_id: String,
  27. pub view_id: String,
  28. pub editor: Arc<DatabaseEditor>,
  29. pub fields: Vec<Arc<Field>>,
  30. pub rows: Vec<Arc<Row>>,
  31. pub field_count: usize,
  32. pub row_by_row_id: HashMap<String, RowPB>,
  33. }
  34. impl DatabaseEditorTest {
  35. pub async fn new_grid() -> Self {
  36. let sdk = FlowyCoreTest::new();
  37. let _ = sdk.init_user().await;
  38. let params = make_test_grid();
  39. let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await;
  40. Self::new(sdk, view_test).await
  41. }
  42. pub async fn new_no_date_grid() -> Self {
  43. let sdk = FlowyCoreTest::new();
  44. let _ = sdk.init_user().await;
  45. let params = make_no_date_test_grid();
  46. let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await;
  47. Self::new(sdk, view_test).await
  48. }
  49. pub async fn new_board() -> Self {
  50. let sdk = FlowyCoreTest::new();
  51. let _ = sdk.init_user().await;
  52. let params = make_test_board();
  53. let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await;
  54. Self::new(sdk, view_test).await
  55. }
  56. pub async fn new_calendar() -> Self {
  57. let sdk = FlowyCoreTest::new();
  58. let _ = sdk.init_user().await;
  59. let params = make_test_calendar();
  60. let view_test = ViewTest::new_grid_view(&sdk, params.to_json_bytes().unwrap()).await;
  61. Self::new(sdk, view_test).await
  62. }
  63. pub async fn new(sdk: FlowyCoreTest, test: ViewTest) -> Self {
  64. let editor = sdk
  65. .database_manager
  66. .get_database_with_view_id(&test.child_view.id)
  67. .await
  68. .unwrap();
  69. let fields = editor
  70. .get_fields(&test.child_view.id, None)
  71. .into_iter()
  72. .map(Arc::new)
  73. .collect();
  74. let rows = editor
  75. .get_rows(&test.child_view.id)
  76. .await
  77. .unwrap()
  78. .into_iter()
  79. .collect();
  80. let view_id = test.child_view.id;
  81. let app_id = test.parent_view.id;
  82. Self {
  83. sdk,
  84. app_id,
  85. view_id,
  86. editor,
  87. fields,
  88. rows,
  89. field_count: FieldType::COUNT,
  90. row_by_row_id: HashMap::default(),
  91. }
  92. }
  93. pub async fn database_filters(&self) -> Vec<FilterPB> {
  94. self.editor.get_all_filters(&self.view_id).await.items
  95. }
  96. pub async fn get_rows(&self) -> Vec<Arc<Row>> {
  97. self.editor.get_rows(&self.view_id).await.unwrap()
  98. }
  99. pub fn get_field(&self, field_id: &str, field_type: FieldType) -> Field {
  100. self
  101. .editor
  102. .get_fields(&self.view_id, None)
  103. .into_iter()
  104. .filter(|field| {
  105. let t_field_type = FieldType::from(field.field_type);
  106. field.id == field_id && t_field_type == field_type
  107. })
  108. .collect::<Vec<_>>()
  109. .pop()
  110. .unwrap()
  111. }
  112. /// returns the first `Field` in the build-in test grid.
  113. /// Not support duplicate `FieldType` in test grid yet.
  114. pub fn get_first_field(&self, field_type: FieldType) -> Field {
  115. self
  116. .editor
  117. .get_fields(&self.view_id, None)
  118. .into_iter()
  119. .filter(|field| {
  120. let t_field_type = FieldType::from(field.field_type);
  121. t_field_type == field_type
  122. })
  123. .collect::<Vec<_>>()
  124. .pop()
  125. .unwrap()
  126. }
  127. pub fn get_fields(&self) -> Vec<Field> {
  128. self.editor.get_fields(&self.view_id, None)
  129. }
  130. pub fn get_multi_select_type_option(&self, field_id: &str) -> Vec<SelectOption> {
  131. let field_type = FieldType::MultiSelect;
  132. let field = self.get_field(field_id, field_type.clone());
  133. let type_option = field
  134. .get_type_option::<MultiSelectTypeOption>(field_type)
  135. .unwrap();
  136. type_option.options
  137. }
  138. pub fn get_single_select_type_option(&self, field_id: &str) -> SingleSelectTypeOption {
  139. let field_type = FieldType::SingleSelect;
  140. let field = self.get_field(field_id, field_type.clone());
  141. field
  142. .get_type_option::<SingleSelectTypeOption>(field_type)
  143. .unwrap()
  144. }
  145. #[allow(dead_code)]
  146. pub fn get_checklist_type_option(&self, field_id: &str) -> ChecklistTypeOption {
  147. let field_type = FieldType::Checklist;
  148. let field = self.get_field(field_id, field_type.clone());
  149. field
  150. .get_type_option::<ChecklistTypeOption>(field_type)
  151. .unwrap()
  152. }
  153. #[allow(dead_code)]
  154. pub fn get_checkbox_type_option(&self, field_id: &str) -> CheckboxTypeOption {
  155. let field_type = FieldType::Checkbox;
  156. let field = self.get_field(field_id, field_type.clone());
  157. field
  158. .get_type_option::<CheckboxTypeOption>(field_type)
  159. .unwrap()
  160. }
  161. pub async fn update_cell<T: ToCellChangeset>(
  162. &mut self,
  163. field_id: &str,
  164. row_id: RowId,
  165. cell_changeset: T,
  166. ) -> FlowyResult<()> {
  167. let field = self
  168. .editor
  169. .get_fields(&self.view_id, None)
  170. .into_iter()
  171. .find(|field| field.id == field_id)
  172. .unwrap();
  173. self
  174. .editor
  175. .update_cell_with_changeset(&self.view_id, row_id, &field.id, cell_changeset)
  176. .await
  177. }
  178. pub(crate) async fn update_text_cell(&mut self, row_id: RowId, content: &str) -> FlowyResult<()> {
  179. let field = self
  180. .editor
  181. .get_fields(&self.view_id, None)
  182. .iter()
  183. .find(|field| {
  184. let field_type = FieldType::from(field.field_type);
  185. field_type == FieldType::RichText
  186. })
  187. .unwrap()
  188. .clone();
  189. self
  190. .update_cell(&field.id, row_id, content.to_string())
  191. .await
  192. }
  193. pub(crate) async fn set_checklist_cell(
  194. &mut self,
  195. row_id: RowId,
  196. f: Box<dyn FnOnce(Vec<SelectOptionPB>) -> Vec<String>>,
  197. ) -> FlowyResult<()> {
  198. let field = self
  199. .editor
  200. .get_fields(&self.view_id, None)
  201. .iter()
  202. .find(|field| {
  203. let field_type = FieldType::from(field.field_type);
  204. field_type == FieldType::Checklist
  205. })
  206. .unwrap()
  207. .clone();
  208. let options = self
  209. .editor
  210. .get_checklist_option(row_id.clone(), &field.id)
  211. .await
  212. .options;
  213. let cell_changeset = ChecklistCellChangeset {
  214. selected_option_ids: f(options),
  215. ..Default::default()
  216. };
  217. self
  218. .editor
  219. .set_checklist_options(&self.view_id, row_id, &field.id, cell_changeset)
  220. .await
  221. }
  222. pub(crate) async fn update_single_select_cell(
  223. &mut self,
  224. row_id: RowId,
  225. option_id: &str,
  226. ) -> FlowyResult<()> {
  227. let field = self
  228. .editor
  229. .get_fields(&self.view_id, None)
  230. .iter()
  231. .find(|field| {
  232. let field_type = FieldType::from(field.field_type);
  233. field_type == FieldType::SingleSelect
  234. })
  235. .unwrap()
  236. .clone();
  237. let cell_changeset = SelectOptionCellChangeset::from_insert_option_id(option_id);
  238. self.update_cell(&field.id, row_id, cell_changeset).await
  239. }
  240. pub async fn import(&self, s: String, format: CSVFormat) -> ImportResult {
  241. self
  242. .sdk
  243. .database_manager
  244. .import_csv(gen_database_view_id(), s, format)
  245. .await
  246. .unwrap()
  247. }
  248. pub async fn get_database(&self, database_id: &str) -> Option<Arc<DatabaseEditor>> {
  249. self
  250. .sdk
  251. .database_manager
  252. .get_database(database_id)
  253. .await
  254. .ok()
  255. }
  256. }
  257. pub struct TestRowBuilder<'a> {
  258. row_id: RowId,
  259. fields: &'a [Field],
  260. cell_build: CellBuilder<'a>,
  261. }
  262. impl<'a> TestRowBuilder<'a> {
  263. pub fn new(row_id: RowId, fields: &'a [Field]) -> Self {
  264. let cell_build = CellBuilder::with_cells(Default::default(), fields);
  265. Self {
  266. row_id,
  267. fields,
  268. cell_build,
  269. }
  270. }
  271. pub fn insert_text_cell(&mut self, data: &str) -> String {
  272. let text_field = self.field_with_type(&FieldType::RichText);
  273. self
  274. .cell_build
  275. .insert_text_cell(&text_field.id, data.to_string());
  276. text_field.id.clone()
  277. }
  278. pub fn insert_number_cell(&mut self, data: &str) -> String {
  279. let number_field = self.field_with_type(&FieldType::Number);
  280. self
  281. .cell_build
  282. .insert_text_cell(&number_field.id, data.to_string());
  283. number_field.id.clone()
  284. }
  285. pub fn insert_date_cell(
  286. &mut self,
  287. data: &str,
  288. time: Option<String>,
  289. include_time: Option<bool>,
  290. field_type: &FieldType,
  291. ) -> String {
  292. let value = serde_json::to_string(&DateCellChangeset {
  293. date: Some(data.to_string()),
  294. time,
  295. include_time,
  296. })
  297. .unwrap();
  298. let date_field = self.field_with_type(field_type);
  299. self.cell_build.insert_text_cell(&date_field.id, value);
  300. date_field.id.clone()
  301. }
  302. pub fn insert_checkbox_cell(&mut self, data: &str) -> String {
  303. let checkbox_field = self.field_with_type(&FieldType::Checkbox);
  304. self
  305. .cell_build
  306. .insert_text_cell(&checkbox_field.id, data.to_string());
  307. checkbox_field.id.clone()
  308. }
  309. pub fn insert_url_cell(&mut self, content: &str) -> String {
  310. let url_field = self.field_with_type(&FieldType::URL);
  311. self
  312. .cell_build
  313. .insert_url_cell(&url_field.id, content.to_string());
  314. url_field.id.clone()
  315. }
  316. pub fn insert_single_select_cell<F>(&mut self, f: F) -> String
  317. where
  318. F: Fn(Vec<SelectOption>) -> SelectOption,
  319. {
  320. let single_select_field = self.field_with_type(&FieldType::SingleSelect);
  321. let type_option = single_select_field
  322. .get_type_option::<SingleSelectTypeOption>(FieldType::SingleSelect)
  323. .unwrap();
  324. let option = f(type_option.options);
  325. self
  326. .cell_build
  327. .insert_select_option_cell(&single_select_field.id, vec![option.id]);
  328. single_select_field.id.clone()
  329. }
  330. pub fn insert_multi_select_cell<F>(&mut self, f: F) -> String
  331. where
  332. F: Fn(Vec<SelectOption>) -> Vec<SelectOption>,
  333. {
  334. let multi_select_field = self.field_with_type(&FieldType::MultiSelect);
  335. let type_option = multi_select_field
  336. .get_type_option::<MultiSelectTypeOption>(FieldType::MultiSelect)
  337. .unwrap();
  338. let options = f(type_option.options);
  339. let ops_ids = options
  340. .iter()
  341. .map(|option| option.id.clone())
  342. .collect::<Vec<_>>();
  343. self
  344. .cell_build
  345. .insert_select_option_cell(&multi_select_field.id, ops_ids);
  346. multi_select_field.id.clone()
  347. }
  348. pub fn insert_checklist_cell(&mut self, option_names: Vec<String>) -> String {
  349. let checklist_field = self.field_with_type(&FieldType::Checklist);
  350. self
  351. .cell_build
  352. .insert_checklist_cell(&checklist_field.id, option_names);
  353. checklist_field.id.clone()
  354. }
  355. pub fn field_with_type(&self, field_type: &FieldType) -> Field {
  356. self
  357. .fields
  358. .iter()
  359. .find(|field| {
  360. let t_field_type = FieldType::from(field.field_type);
  361. &t_field_type == field_type
  362. })
  363. .unwrap()
  364. .clone()
  365. }
  366. pub fn build(self) -> CreateRowParams {
  367. CreateRowParams {
  368. id: self.row_id,
  369. cells: self.cell_build.build(),
  370. height: 60,
  371. visibility: true,
  372. prev_row_id: None,
  373. timestamp: timestamp(),
  374. }
  375. }
  376. }