configuration.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. use crate::entities::{GroupChangesetPB, GroupPB, InsertedGroupPB};
  2. use crate::services::field::RowSingleCellData;
  3. use crate::services::group::{
  4. default_group_setting, GeneratedGroupContext, Group, GroupData, GroupSetting,
  5. };
  6. use collab_database::fields::Field;
  7. use flowy_error::{FlowyError, FlowyResult};
  8. use indexmap::IndexMap;
  9. use lib_infra::future::Fut;
  10. use serde::de::DeserializeOwned;
  11. use serde::Serialize;
  12. use std::collections::HashMap;
  13. use std::fmt::Formatter;
  14. use std::marker::PhantomData;
  15. use std::sync::Arc;
  16. pub trait GroupSettingReader: Send + Sync + 'static {
  17. fn get_group_setting(&self, view_id: &str) -> Fut<Option<Arc<GroupSetting>>>;
  18. fn get_configuration_cells(&self, view_id: &str, field_id: &str) -> Fut<Vec<RowSingleCellData>>;
  19. }
  20. pub trait GroupSettingWriter: Send + Sync + 'static {
  21. fn save_configuration(&self, view_id: &str, group_setting: GroupSetting) -> Fut<FlowyResult<()>>;
  22. }
  23. impl<T> std::fmt::Display for GroupContext<T> {
  24. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  25. self.groups_map.iter().for_each(|(_, group)| {
  26. let _ = f.write_fmt(format_args!(
  27. "Group:{} has {} rows \n",
  28. group.id,
  29. group.rows.len()
  30. ));
  31. });
  32. Ok(())
  33. }
  34. }
  35. /// A [GroupContext] represents as the groups memory cache
  36. /// Each [GenericGroupController] has its own [GroupContext], the `context` has its own configuration
  37. /// that is restored from the disk.
  38. ///
  39. /// The `context` contains a list of [GroupData]s and the grouping [Field]
  40. pub struct GroupContext<C> {
  41. pub view_id: String,
  42. /// The group configuration restored from the disk.
  43. ///
  44. /// Uses the [GroupSettingReader] to read the configuration data from disk
  45. setting: Arc<GroupSetting>,
  46. configuration_phantom: PhantomData<C>,
  47. /// The grouping field
  48. field: Arc<Field>,
  49. /// Cache all the groups
  50. groups_map: IndexMap<String, GroupData>,
  51. /// A reader that implement the [GroupSettingReader] trait
  52. ///
  53. #[allow(dead_code)]
  54. reader: Arc<dyn GroupSettingReader>,
  55. /// A writer that implement the [GroupSettingWriter] trait is used to save the
  56. /// configuration to disk
  57. ///
  58. writer: Arc<dyn GroupSettingWriter>,
  59. }
  60. impl<C> GroupContext<C>
  61. where
  62. C: Serialize + DeserializeOwned,
  63. {
  64. #[tracing::instrument(level = "trace", skip_all, err)]
  65. pub async fn new(
  66. view_id: String,
  67. field: Arc<Field>,
  68. reader: Arc<dyn GroupSettingReader>,
  69. writer: Arc<dyn GroupSettingWriter>,
  70. ) -> FlowyResult<Self> {
  71. let setting = match reader.get_group_setting(&view_id).await {
  72. None => {
  73. let default_configuration = default_group_setting(&field);
  74. writer
  75. .save_configuration(&view_id, default_configuration.clone())
  76. .await?;
  77. Arc::new(default_configuration)
  78. },
  79. Some(setting) => setting,
  80. };
  81. Ok(Self {
  82. view_id,
  83. field,
  84. groups_map: IndexMap::new(),
  85. reader,
  86. writer,
  87. setting,
  88. configuration_phantom: PhantomData,
  89. })
  90. }
  91. /// Returns the no `status` group
  92. ///
  93. /// We take the `id` of the `field` as the no status group id
  94. pub(crate) fn get_no_status_group(&self) -> Option<&GroupData> {
  95. self.groups_map.get(&self.field.id)
  96. }
  97. pub(crate) fn get_mut_no_status_group(&mut self) -> Option<&mut GroupData> {
  98. self.groups_map.get_mut(&self.field.id)
  99. }
  100. pub(crate) fn groups(&self) -> Vec<&GroupData> {
  101. self.groups_map.values().collect()
  102. }
  103. pub(crate) fn get_mut_group(&mut self, group_id: &str) -> Option<&mut GroupData> {
  104. self.groups_map.get_mut(group_id)
  105. }
  106. // Returns the index and group specified by the group_id
  107. pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &GroupData)> {
  108. match (
  109. self.groups_map.get_index_of(group_id),
  110. self.groups_map.get(group_id),
  111. ) {
  112. (Some(index), Some(group)) => Some((index, group)),
  113. _ => None,
  114. }
  115. }
  116. /// Iterate mut the groups without `No status` group
  117. pub(crate) fn iter_mut_status_groups(&mut self, mut each: impl FnMut(&mut GroupData)) {
  118. self.groups_map.iter_mut().for_each(|(_, group)| {
  119. if group.id != self.field.id {
  120. each(group);
  121. }
  122. });
  123. }
  124. pub(crate) fn iter_mut_groups(&mut self, mut each: impl FnMut(&mut GroupData)) {
  125. self.groups_map.iter_mut().for_each(|(_, group)| {
  126. each(group);
  127. });
  128. }
  129. #[tracing::instrument(level = "trace", skip(self), err)]
  130. pub(crate) fn add_new_group(&mut self, group: Group) -> FlowyResult<InsertedGroupPB> {
  131. let group_data = GroupData::new(
  132. group.id.clone(),
  133. self.field.id.clone(),
  134. group.name.clone(),
  135. group.id.clone(),
  136. );
  137. self.groups_map.insert(group.id.clone(), group_data);
  138. let (index, group_data) = self.get_group(&group.id).unwrap();
  139. let insert_group = InsertedGroupPB {
  140. group: GroupPB::from(group_data.clone()),
  141. index: index as i32,
  142. };
  143. self.mut_configuration(|configuration| {
  144. configuration.groups.push(group);
  145. true
  146. })?;
  147. Ok(insert_group)
  148. }
  149. #[tracing::instrument(level = "trace", skip(self))]
  150. pub(crate) fn delete_group(&mut self, deleted_group_id: &str) -> FlowyResult<()> {
  151. self.groups_map.remove(deleted_group_id);
  152. self.mut_configuration(|configuration| {
  153. configuration
  154. .groups
  155. .retain(|group| group.id != deleted_group_id);
  156. true
  157. })?;
  158. Ok(())
  159. }
  160. pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> {
  161. let from_index = self.groups_map.get_index_of(from_id);
  162. let to_index = self.groups_map.get_index_of(to_id);
  163. match (from_index, to_index) {
  164. (Some(from_index), Some(to_index)) => {
  165. self.groups_map.move_index(from_index, to_index);
  166. self.mut_configuration(|configuration| {
  167. let from_index = configuration
  168. .groups
  169. .iter()
  170. .position(|group| group.id == from_id);
  171. let to_index = configuration
  172. .groups
  173. .iter()
  174. .position(|group| group.id == to_id);
  175. if let (Some(from), Some(to)) = &(from_index, to_index) {
  176. tracing::trace!(
  177. "Move group from index:{:?} to index:{:?}",
  178. from_index,
  179. to_index
  180. );
  181. let group = configuration.groups.remove(*from);
  182. configuration.groups.insert(*to, group);
  183. }
  184. tracing::debug!(
  185. "Group order: {:?} ",
  186. configuration
  187. .groups
  188. .iter()
  189. .map(|group| group.name.clone())
  190. .collect::<Vec<String>>()
  191. .join(",")
  192. );
  193. from_index.is_some() && to_index.is_some()
  194. })?;
  195. Ok(())
  196. },
  197. _ => Err(FlowyError::record_not_found().context("Moving group failed. Groups are not exist")),
  198. }
  199. }
  200. /// Reset the memory cache of the groups and update the group configuration
  201. ///
  202. /// # Arguments
  203. ///
  204. /// * `generated_group_configs`: the generated groups contains a list of [GeneratedGroupConfig].
  205. ///
  206. /// Each [FieldType] can implement the [GroupGenerator] trait in order to generate different
  207. /// groups. For example, the FieldType::Checkbox has the [CheckboxGroupGenerator] that implements
  208. /// the [GroupGenerator] trait.
  209. ///
  210. /// Consider the passed-in generated_group_configs as new groups, the groups in the current
  211. /// [GroupConfigurationRevision] as old groups. The old groups and the new groups will be merged
  212. /// while keeping the order of the old groups.
  213. ///
  214. #[tracing::instrument(level = "trace", skip(self, generated_group_context), err)]
  215. pub(crate) fn init_groups(
  216. &mut self,
  217. generated_group_context: GeneratedGroupContext,
  218. ) -> FlowyResult<Option<GroupChangesetPB>> {
  219. let GeneratedGroupContext {
  220. no_status_group,
  221. group_configs,
  222. } = generated_group_context;
  223. let mut new_groups = vec![];
  224. let mut filter_content_map = HashMap::new();
  225. group_configs.into_iter().for_each(|generate_group| {
  226. filter_content_map.insert(
  227. generate_group.group.id.clone(),
  228. generate_group.filter_content,
  229. );
  230. new_groups.push(generate_group.group);
  231. });
  232. let mut old_groups = self.setting.groups.clone();
  233. // clear all the groups if grouping by a new field
  234. if self.setting.field_id != self.field.id {
  235. old_groups.clear();
  236. }
  237. // The `all_group_revs` is the combination of the new groups and old groups
  238. let MergeGroupResult {
  239. mut all_groups,
  240. new_groups,
  241. deleted_groups,
  242. } = merge_groups(no_status_group, old_groups, new_groups);
  243. let deleted_group_ids = deleted_groups
  244. .into_iter()
  245. .map(|group_rev| group_rev.id)
  246. .collect::<Vec<String>>();
  247. self.mut_configuration(|configuration| {
  248. let mut is_changed = !deleted_group_ids.is_empty();
  249. // Remove the groups
  250. configuration
  251. .groups
  252. .retain(|group| !deleted_group_ids.contains(&group.id));
  253. // Update/Insert new groups
  254. for group in &mut all_groups {
  255. match configuration
  256. .groups
  257. .iter()
  258. .position(|old_group_rev| old_group_rev.id == group.id)
  259. {
  260. None => {
  261. // Push the group to the end of the list if it doesn't exist in the group
  262. configuration.groups.push(group.clone());
  263. is_changed = true;
  264. },
  265. Some(pos) => {
  266. let mut old_group = configuration.groups.get_mut(pos).unwrap();
  267. // Take the old group setting
  268. group.visible = old_group.visible;
  269. if !is_changed {
  270. is_changed = is_group_changed(group, old_group);
  271. }
  272. // Consider the the name of the `group_rev` as the newest.
  273. old_group.name = group.name.clone();
  274. },
  275. }
  276. }
  277. is_changed
  278. })?;
  279. // Update the memory cache of the groups
  280. all_groups.into_iter().for_each(|group_rev| {
  281. let filter_content = filter_content_map
  282. .get(&group_rev.id)
  283. .cloned()
  284. .unwrap_or_else(|| "".to_owned());
  285. let group = GroupData::new(
  286. group_rev.id,
  287. self.field.id.clone(),
  288. group_rev.name,
  289. filter_content,
  290. );
  291. self.groups_map.insert(group.id.clone(), group);
  292. });
  293. let initial_groups = new_groups
  294. .into_iter()
  295. .flat_map(|group_rev| {
  296. let filter_content = filter_content_map.get(&group_rev.id)?;
  297. let group = GroupData::new(
  298. group_rev.id,
  299. self.field.id.clone(),
  300. group_rev.name,
  301. filter_content.clone(),
  302. );
  303. Some(GroupPB::from(group))
  304. })
  305. .collect();
  306. let changeset = GroupChangesetPB {
  307. view_id: self.view_id.clone(),
  308. initial_groups,
  309. deleted_groups: deleted_group_ids,
  310. update_groups: vec![],
  311. inserted_groups: vec![],
  312. };
  313. tracing::trace!("Group changeset: {:?}", changeset);
  314. if changeset.is_empty() {
  315. Ok(None)
  316. } else {
  317. Ok(Some(changeset))
  318. }
  319. }
  320. #[allow(dead_code)]
  321. pub(crate) async fn hide_group(&mut self, group_id: &str) -> FlowyResult<()> {
  322. self.mut_group_rev(group_id, |group_rev| {
  323. group_rev.visible = false;
  324. })?;
  325. Ok(())
  326. }
  327. #[allow(dead_code)]
  328. pub(crate) async fn show_group(&mut self, group_id: &str) -> FlowyResult<()> {
  329. self.mut_group_rev(group_id, |group_rev| {
  330. group_rev.visible = true;
  331. })?;
  332. Ok(())
  333. }
  334. pub(crate) async fn get_all_cells(&self) -> Vec<RowSingleCellData> {
  335. self
  336. .reader
  337. .get_configuration_cells(&self.view_id, &self.field.id)
  338. .await
  339. }
  340. fn mut_configuration(
  341. &mut self,
  342. mut_configuration_fn: impl FnOnce(&mut GroupSetting) -> bool,
  343. ) -> FlowyResult<()> {
  344. let configuration = Arc::make_mut(&mut self.setting);
  345. let is_changed = mut_configuration_fn(configuration);
  346. if is_changed {
  347. let configuration = (*self.setting).clone();
  348. let writer = self.writer.clone();
  349. let view_id = self.view_id.clone();
  350. tokio::spawn(async move {
  351. match writer.save_configuration(&view_id, configuration).await {
  352. Ok(_) => {},
  353. Err(e) => {
  354. tracing::error!("Save group configuration failed: {}", e);
  355. },
  356. }
  357. });
  358. }
  359. Ok(())
  360. }
  361. fn mut_group_rev(
  362. &mut self,
  363. group_id: &str,
  364. mut_groups_fn: impl Fn(&mut Group),
  365. ) -> FlowyResult<()> {
  366. self.mut_configuration(|configuration| {
  367. match configuration
  368. .groups
  369. .iter_mut()
  370. .find(|group| group.id == group_id)
  371. {
  372. None => false,
  373. Some(group) => {
  374. mut_groups_fn(group);
  375. true
  376. },
  377. }
  378. })
  379. }
  380. }
  381. /// Merge the new groups into old groups while keeping the order in the old groups
  382. ///
  383. fn merge_groups(
  384. no_status_group: Option<Group>,
  385. old_groups: Vec<Group>,
  386. new_groups: Vec<Group>,
  387. ) -> MergeGroupResult {
  388. let mut merge_result = MergeGroupResult::new();
  389. // group_map is a helper map is used to filter out the new groups.
  390. let mut new_group_map: IndexMap<String, Group> = IndexMap::new();
  391. new_groups.into_iter().for_each(|group_rev| {
  392. new_group_map.insert(group_rev.id.clone(), group_rev);
  393. });
  394. // The group is ordered in old groups. Add them before adding the new groups
  395. for old in old_groups {
  396. if let Some(new) = new_group_map.remove(&old.id) {
  397. merge_result.all_groups.push(new.clone());
  398. } else {
  399. merge_result.deleted_groups.push(old);
  400. }
  401. }
  402. // Find out the new groups
  403. let new_groups = new_group_map.into_values();
  404. for (_, group) in new_groups.into_iter().enumerate() {
  405. merge_result.all_groups.push(group.clone());
  406. merge_result.new_groups.push(group);
  407. }
  408. // The `No status` group index is initialized to 0
  409. if let Some(no_status_group) = no_status_group {
  410. merge_result.all_groups.insert(0, no_status_group);
  411. }
  412. merge_result
  413. }
  414. fn is_group_changed(new: &Group, old: &Group) -> bool {
  415. if new.name != old.name {
  416. return true;
  417. }
  418. false
  419. }
  420. struct MergeGroupResult {
  421. // Contains the new groups and the updated groups
  422. all_groups: Vec<Group>,
  423. new_groups: Vec<Group>,
  424. deleted_groups: Vec<Group>,
  425. }
  426. impl MergeGroupResult {
  427. fn new() -> Self {
  428. Self {
  429. all_groups: vec![],
  430. new_groups: vec![],
  431. deleted_groups: vec![],
  432. }
  433. }
  434. }