grid_view_editor.rs 20 KB

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