grid_view_editor.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. use crate::dart_notification::{send_dart_notification, GridNotification};
  2. use crate::entities::{
  3. CreateRowParams, DeleteFilterParams, DeleteGroupParams, GridFilterConfigurationPB, GridGroupConfigurationPB,
  4. GridLayout, GridLayoutPB, GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertFilterParams,
  5. InsertGroupParams, InsertedGroupPB, InsertedRowPB, MoveGroupParams, RepeatedGridFilterConfigurationPB,
  6. RepeatedGridGroupConfigurationPB, RowPB,
  7. };
  8. use crate::services::grid_editor_task::GridServiceTaskScheduler;
  9. use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
  10. use crate::services::group::{
  11. default_group_configuration, find_group_field, make_group_controller, GroupConfigurationReader,
  12. GroupConfigurationWriter, GroupController, MoveGroupRowContext,
  13. };
  14. use flowy_error::{FlowyError, FlowyResult};
  15. use flowy_grid_data_model::revision::{
  16. gen_grid_filter_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision,
  17. RowChangeset, RowRevision,
  18. };
  19. use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilder};
  20. use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
  21. use flowy_sync::entities::revision::Revision;
  22. use lib_infra::future::{wrap_future, AFFuture, FutureResult};
  23. use std::future::Future;
  24. use std::sync::Arc;
  25. use tokio::sync::RwLock;
  26. #[allow(dead_code)]
  27. pub struct GridViewRevisionEditor {
  28. user_id: String,
  29. view_id: String,
  30. pad: Arc<RwLock<GridViewRevisionPad>>,
  31. rev_manager: Arc<RevisionManager>,
  32. field_delegate: Arc<dyn GridViewFieldDelegate>,
  33. row_delegate: Arc<dyn GridViewRowDelegate>,
  34. group_controller: Arc<RwLock<Box<dyn GroupController>>>,
  35. scheduler: Arc<dyn GridServiceTaskScheduler>,
  36. }
  37. impl GridViewRevisionEditor {
  38. #[tracing::instrument(level = "trace", skip_all, err)]
  39. pub(crate) async fn new(
  40. user_id: &str,
  41. token: &str,
  42. view_id: String,
  43. field_delegate: Arc<dyn GridViewFieldDelegate>,
  44. row_delegate: Arc<dyn GridViewRowDelegate>,
  45. scheduler: Arc<dyn GridServiceTaskScheduler>,
  46. mut rev_manager: RevisionManager,
  47. ) -> FlowyResult<Self> {
  48. let cloud = Arc::new(GridViewRevisionCloudService {
  49. token: token.to_owned(),
  50. });
  51. let view_revision_pad = rev_manager.load::<GridViewRevisionPadBuilder>(Some(cloud)).await?;
  52. let pad = Arc::new(RwLock::new(view_revision_pad));
  53. let rev_manager = Arc::new(rev_manager);
  54. let group_controller = new_group_controller(
  55. user_id.to_owned(),
  56. view_id.clone(),
  57. pad.clone(),
  58. rev_manager.clone(),
  59. field_delegate.clone(),
  60. row_delegate.clone(),
  61. )
  62. .await?;
  63. let user_id = user_id.to_owned();
  64. Ok(Self {
  65. pad,
  66. user_id,
  67. view_id,
  68. rev_manager,
  69. scheduler,
  70. field_delegate,
  71. row_delegate,
  72. group_controller: Arc::new(RwLock::new(group_controller)),
  73. })
  74. }
  75. pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) {
  76. if params.group_id.is_none() {
  77. return;
  78. }
  79. let group_id = params.group_id.as_ref().unwrap();
  80. let _ = self
  81. .mut_group_controller(|group_controller, field_rev| {
  82. group_controller.will_create_row(row_rev, &field_rev, group_id);
  83. Ok(())
  84. })
  85. .await;
  86. }
  87. pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) {
  88. // Send the group notification if the current view has groups
  89. match params.group_id.as_ref() {
  90. None => {}
  91. Some(group_id) => {
  92. let index = match params.start_row_id {
  93. None => Some(0),
  94. Some(_) => None,
  95. };
  96. let inserted_row = InsertedRowPB {
  97. row: row_pb.clone(),
  98. index,
  99. is_new: true,
  100. };
  101. let changeset = GroupChangesetPB::insert(group_id.clone(), vec![inserted_row]);
  102. self.notify_did_update_group(changeset).await;
  103. }
  104. }
  105. }
  106. pub(crate) async fn did_delete_row(&self, row_rev: &RowRevision) {
  107. // Send the group notification if the current view has groups;
  108. let changesets = self
  109. .mut_group_controller(|group_controller, field_rev| group_controller.did_delete_row(row_rev, &field_rev))
  110. .await;
  111. if let Some(changesets) = changesets {
  112. for changeset in changesets {
  113. self.notify_did_update_group(changeset).await;
  114. }
  115. }
  116. }
  117. pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) {
  118. let changesets = self
  119. .mut_group_controller(|group_controller, field_rev| group_controller.did_update_row(row_rev, &field_rev))
  120. .await;
  121. if let Some(changesets) = changesets {
  122. for changeset in changesets {
  123. self.notify_did_update_group(changeset).await;
  124. }
  125. }
  126. }
  127. pub(crate) async fn move_group_row(
  128. &self,
  129. row_rev: &RowRevision,
  130. row_changeset: &mut RowChangeset,
  131. to_group_id: &str,
  132. to_row_id: Option<String>,
  133. ) -> Vec<GroupChangesetPB> {
  134. let changesets = self
  135. .mut_group_controller(|group_controller, field_rev| {
  136. let move_row_context = MoveGroupRowContext {
  137. row_rev,
  138. row_changeset,
  139. field_rev: field_rev.as_ref(),
  140. to_group_id,
  141. to_row_id,
  142. };
  143. let changesets = group_controller.move_group_row(move_row_context)?;
  144. Ok(changesets)
  145. })
  146. .await;
  147. changesets.unwrap_or_default()
  148. }
  149. /// Only call once after grid view editor initialized
  150. #[tracing::instrument(level = "trace", skip(self))]
  151. pub(crate) async fn load_groups(&self) -> FlowyResult<Vec<GroupPB>> {
  152. let groups = self.group_controller.read().await.groups();
  153. tracing::trace!("Number of groups: {}", groups.len());
  154. Ok(groups.into_iter().map(GroupPB::from).collect())
  155. }
  156. pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
  157. let _ = self
  158. .group_controller
  159. .write()
  160. .await
  161. .move_group(&params.from_group_id, &params.to_group_id)?;
  162. match self.group_controller.read().await.get_group(&params.from_group_id) {
  163. None => {}
  164. Some((index, group)) => {
  165. let inserted_group = InsertedGroupPB {
  166. group: GroupPB::from(group),
  167. index: index as i32,
  168. };
  169. let changeset = GroupViewChangesetPB {
  170. view_id: self.view_id.clone(),
  171. inserted_groups: vec![inserted_group],
  172. deleted_groups: vec![params.from_group_id.clone()],
  173. update_groups: vec![],
  174. new_groups: vec![],
  175. };
  176. self.notify_did_update_view(changeset).await;
  177. }
  178. }
  179. Ok(())
  180. }
  181. pub(crate) async fn get_setting(&self) -> GridSettingPB {
  182. let field_revs = self.field_delegate.get_field_revs().await;
  183. let grid_setting = make_grid_setting(&*self.pad.read().await, &field_revs);
  184. grid_setting
  185. }
  186. pub(crate) async fn get_filters(&self) -> Vec<GridFilterConfigurationPB> {
  187. let field_revs = self.field_delegate.get_field_revs().await;
  188. match self.pad.read().await.get_all_filters(&field_revs) {
  189. None => vec![],
  190. Some(filters) => filters
  191. .into_values()
  192. .flatten()
  193. .map(|filter| GridFilterConfigurationPB::from(filter.as_ref()))
  194. .collect(),
  195. }
  196. }
  197. pub(crate) async fn insert_group(&self, params: InsertGroupParams) -> FlowyResult<()> {
  198. if let Some(field_rev) = self.field_delegate.get_field_rev(&params.field_id).await {
  199. let _ = self
  200. .modify(|pad| {
  201. let configuration = default_group_configuration(&field_rev);
  202. let changeset = pad.insert_group(&params.field_id, &params.field_type_rev, configuration)?;
  203. Ok(changeset)
  204. })
  205. .await?;
  206. }
  207. if self.group_controller.read().await.field_id() != params.field_id {
  208. let _ = self.group_by_field(&params.field_id).await?;
  209. self.notify_did_update_setting().await;
  210. }
  211. Ok(())
  212. }
  213. pub(crate) async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> {
  214. self.modify(|pad| {
  215. let changeset = pad.delete_filter(&params.field_id, &params.field_type_rev, &params.group_id)?;
  216. Ok(changeset)
  217. })
  218. .await
  219. }
  220. pub(crate) async fn insert_filter(&self, params: InsertFilterParams) -> FlowyResult<()> {
  221. self.modify(|pad| {
  222. let filter_rev = FilterConfigurationRevision {
  223. id: gen_grid_filter_id(),
  224. field_id: params.field_id.clone(),
  225. condition: params.condition,
  226. content: params.content,
  227. };
  228. let changeset = pad.insert_filter(&params.field_id, &params.field_type_rev, filter_rev)?;
  229. Ok(changeset)
  230. })
  231. .await
  232. }
  233. pub(crate) async fn delete_filter(&self, delete_filter: DeleteFilterParams) -> FlowyResult<()> {
  234. self.modify(|pad| {
  235. let changeset = pad.delete_filter(
  236. &delete_filter.field_id,
  237. &delete_filter.field_type_rev,
  238. &delete_filter.filter_id,
  239. )?;
  240. Ok(changeset)
  241. })
  242. .await
  243. }
  244. #[tracing::instrument(level = "trace", skip_all, err)]
  245. pub(crate) async fn did_update_field(&self, field_id: &str) -> FlowyResult<()> {
  246. if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
  247. match self.group_controller.write().await.did_update_field(&field_rev)? {
  248. None => {}
  249. Some(changeset) => {
  250. self.notify_did_update_view(changeset).await;
  251. }
  252. }
  253. }
  254. Ok(())
  255. }
  256. pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
  257. if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
  258. let new_group_controller = new_group_controller_with_field_rev(
  259. self.user_id.clone(),
  260. self.view_id.clone(),
  261. self.pad.clone(),
  262. self.rev_manager.clone(),
  263. field_rev,
  264. self.row_delegate.clone(),
  265. )
  266. .await?;
  267. let new_groups = new_group_controller.groups().into_iter().map(GroupPB::from).collect();
  268. *self.group_controller.write().await = new_group_controller;
  269. let changeset = GroupViewChangesetPB {
  270. view_id: self.view_id.clone(),
  271. new_groups,
  272. ..Default::default()
  273. };
  274. debug_assert!(!changeset.is_empty());
  275. if !changeset.is_empty() {
  276. send_dart_notification(&changeset.view_id, GridNotification::DidGroupByNewField)
  277. .payload(changeset)
  278. .send();
  279. }
  280. }
  281. Ok(())
  282. }
  283. async fn notify_did_update_setting(&self) {
  284. let setting = self.get_setting().await;
  285. send_dart_notification(&self.view_id, GridNotification::DidUpdateGridSetting)
  286. .payload(setting)
  287. .send();
  288. }
  289. pub async fn notify_did_update_group(&self, changeset: GroupChangesetPB) {
  290. send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup)
  291. .payload(changeset)
  292. .send();
  293. }
  294. async fn notify_did_update_view(&self, changeset: GroupViewChangesetPB) {
  295. send_dart_notification(&self.view_id, GridNotification::DidUpdateGroupView)
  296. .payload(changeset)
  297. .send();
  298. }
  299. async fn modify<F>(&self, f: F) -> FlowyResult<()>
  300. where
  301. F: for<'a> FnOnce(&'a mut GridViewRevisionPad) -> FlowyResult<Option<GridViewRevisionChangeset>>,
  302. {
  303. let mut write_guard = self.pad.write().await;
  304. match f(&mut *write_guard)? {
  305. None => {}
  306. Some(change) => {
  307. let _ = apply_change(&self.user_id, self.rev_manager.clone(), change).await?;
  308. }
  309. }
  310. Ok(())
  311. }
  312. async fn mut_group_controller<F, T>(&self, f: F) -> Option<T>
  313. where
  314. F: FnOnce(&mut Box<dyn GroupController>, Arc<FieldRevision>) -> FlowyResult<T>,
  315. {
  316. let group_field_id = self.group_controller.read().await.field_id().to_owned();
  317. match self.field_delegate.get_field_rev(&group_field_id).await {
  318. None => None,
  319. Some(field_rev) => {
  320. let mut write_guard = self.group_controller.write().await;
  321. f(&mut write_guard, field_rev).ok()
  322. }
  323. }
  324. }
  325. #[allow(dead_code)]
  326. async fn async_mut_group_controller<F, O, T>(&self, f: F) -> Option<T>
  327. where
  328. F: FnOnce(Arc<RwLock<Box<dyn GroupController>>>, Arc<FieldRevision>) -> O,
  329. O: Future<Output = FlowyResult<T>> + Sync + 'static,
  330. {
  331. let group_field_id = self.group_controller.read().await.field_id().to_owned();
  332. match self.field_delegate.get_field_rev(&group_field_id).await {
  333. None => None,
  334. Some(field_rev) => {
  335. let _write_guard = self.group_controller.write().await;
  336. f(self.group_controller.clone(), field_rev).await.ok()
  337. }
  338. }
  339. }
  340. }
  341. async fn new_group_controller(
  342. user_id: String,
  343. view_id: String,
  344. pad: Arc<RwLock<GridViewRevisionPad>>,
  345. rev_manager: Arc<RevisionManager>,
  346. field_delegate: Arc<dyn GridViewFieldDelegate>,
  347. row_delegate: Arc<dyn GridViewRowDelegate>,
  348. ) -> FlowyResult<Box<dyn GroupController>> {
  349. let configuration_reader = GroupConfigurationReaderImpl(pad.clone());
  350. let field_revs = field_delegate.get_field_revs().await;
  351. // Read the group field or find a new group field
  352. let field_rev = configuration_reader
  353. .get_configuration()
  354. .await
  355. .and_then(|configuration| {
  356. field_revs
  357. .iter()
  358. .find(|field_rev| field_rev.id == configuration.field_id)
  359. .cloned()
  360. })
  361. .unwrap_or_else(|| find_group_field(&field_revs).unwrap());
  362. new_group_controller_with_field_rev(user_id, view_id, pad, rev_manager, field_rev, row_delegate).await
  363. }
  364. async fn new_group_controller_with_field_rev(
  365. user_id: String,
  366. view_id: String,
  367. pad: Arc<RwLock<GridViewRevisionPad>>,
  368. rev_manager: Arc<RevisionManager>,
  369. field_rev: Arc<FieldRevision>,
  370. row_delegate: Arc<dyn GridViewRowDelegate>,
  371. ) -> FlowyResult<Box<dyn GroupController>> {
  372. let configuration_reader = GroupConfigurationReaderImpl(pad.clone());
  373. let configuration_writer = GroupConfigurationWriterImpl {
  374. user_id,
  375. rev_manager,
  376. view_pad: pad,
  377. };
  378. let row_revs = row_delegate.gv_row_revs().await;
  379. make_group_controller(view_id, field_rev, row_revs, configuration_reader, configuration_writer).await
  380. }
  381. async fn apply_change(
  382. user_id: &str,
  383. rev_manager: Arc<RevisionManager>,
  384. change: GridViewRevisionChangeset,
  385. ) -> FlowyResult<()> {
  386. let GridViewRevisionChangeset { delta, md5 } = change;
  387. let (base_rev_id, rev_id) = rev_manager.next_rev_id_pair();
  388. let delta_data = delta.json_bytes();
  389. let revision = Revision::new(&rev_manager.object_id, base_rev_id, rev_id, delta_data, user_id, md5);
  390. let _ = rev_manager.add_local_revision(&revision).await?;
  391. Ok(())
  392. }
  393. struct GridViewRevisionCloudService {
  394. #[allow(dead_code)]
  395. token: String,
  396. }
  397. impl RevisionCloudService for GridViewRevisionCloudService {
  398. #[tracing::instrument(level = "trace", skip(self))]
  399. fn fetch_object(&self, _user_id: &str, _object_id: &str) -> FutureResult<Vec<Revision>, FlowyError> {
  400. FutureResult::new(async move { Ok(vec![]) })
  401. }
  402. }
  403. struct GridViewRevisionPadBuilder();
  404. impl RevisionObjectBuilder for GridViewRevisionPadBuilder {
  405. type Output = GridViewRevisionPad;
  406. fn build_object(object_id: &str, revisions: Vec<Revision>) -> FlowyResult<Self::Output> {
  407. let pad = GridViewRevisionPad::from_revisions(object_id, revisions)?;
  408. Ok(pad)
  409. }
  410. }
  411. struct GroupConfigurationReaderImpl(Arc<RwLock<GridViewRevisionPad>>);
  412. impl GroupConfigurationReader for GroupConfigurationReaderImpl {
  413. fn get_configuration(&self) -> AFFuture<Option<Arc<GroupConfigurationRevision>>> {
  414. let view_pad = self.0.clone();
  415. wrap_future(async move {
  416. let mut groups = view_pad.read().await.get_all_groups();
  417. if groups.is_empty() {
  418. None
  419. } else {
  420. debug_assert_eq!(groups.len(), 1);
  421. Some(groups.pop().unwrap())
  422. }
  423. })
  424. }
  425. }
  426. struct GroupConfigurationWriterImpl {
  427. user_id: String,
  428. rev_manager: Arc<RevisionManager>,
  429. view_pad: Arc<RwLock<GridViewRevisionPad>>,
  430. }
  431. impl GroupConfigurationWriter for GroupConfigurationWriterImpl {
  432. fn save_configuration(
  433. &self,
  434. field_id: &str,
  435. field_type: FieldTypeRevision,
  436. group_configuration: GroupConfigurationRevision,
  437. ) -> AFFuture<FlowyResult<()>> {
  438. let user_id = self.user_id.clone();
  439. let rev_manager = self.rev_manager.clone();
  440. let view_pad = self.view_pad.clone();
  441. let field_id = field_id.to_owned();
  442. wrap_future(async move {
  443. let changeset = view_pad
  444. .write()
  445. .await
  446. .insert_group(&field_id, &field_type, group_configuration)?;
  447. if let Some(changeset) = changeset {
  448. let _ = apply_change(&user_id, rev_manager, changeset).await?;
  449. }
  450. Ok(())
  451. })
  452. }
  453. }
  454. pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc<FieldRevision>]) -> GridSettingPB {
  455. let layout_type: GridLayout = view_pad.layout.clone().into();
  456. let filter_configurations = view_pad
  457. .get_all_filters(field_revs)
  458. .map(|filters_by_field_id| {
  459. filters_by_field_id
  460. .into_iter()
  461. .map(|(_, v)| {
  462. let repeated_filter: RepeatedGridFilterConfigurationPB = v.into();
  463. repeated_filter.items
  464. })
  465. .flatten()
  466. .collect::<Vec<GridFilterConfigurationPB>>()
  467. })
  468. .unwrap_or_default();
  469. let group_configurations = view_pad
  470. .get_groups_by_field_revs(field_revs)
  471. .map(|groups_by_field_id| {
  472. groups_by_field_id
  473. .into_iter()
  474. .map(|(_, v)| {
  475. let repeated_group: RepeatedGridGroupConfigurationPB = v.into();
  476. repeated_group.items
  477. })
  478. .flatten()
  479. .collect::<Vec<GridGroupConfigurationPB>>()
  480. })
  481. .unwrap_or_default();
  482. GridSettingPB {
  483. layouts: GridLayoutPB::all(),
  484. layout_type,
  485. filter_configurations: filter_configurations.into(),
  486. group_configurations: group_configurations.into(),
  487. }
  488. }
  489. #[cfg(test)]
  490. mod tests {
  491. use lib_ot::core::TextDelta;
  492. #[test]
  493. fn test() {
  494. let s1 = r#"[{"insert":"{\"view_id\":\"fTURELffPr\",\"grid_id\":\"fTURELffPr\",\"layout\":0,\"filters\":[],\"groups\":[]}"}]"#;
  495. let _delta_1 = TextDelta::from_json(s1).unwrap();
  496. let s2 = r#"[{"retain":195},{"insert":"{\\\"group_id\\\":\\\"wD9i\\\",\\\"visible\\\":true},{\\\"group_id\\\":\\\"xZtv\\\",\\\"visible\\\":true},{\\\"group_id\\\":\\\"tFV2\\\",\\\"visible\\\":true}"},{"retain":10}]"#;
  497. let _delta_2 = TextDelta::from_json(s2).unwrap();
  498. }
  499. }