database_editor.rs 10.0 KB

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