database_editor.rs 11 KB

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