configuration.rs 14 KB

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