configuration.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. use crate::entities::{GroupPB, GroupViewChangesetPB, InsertedGroupPB};
  2. use crate::services::group::{default_group_configuration, GeneratedGroup, 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, field_rev: Arc<FieldRevision>) -> 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. let _ = f.write_fmt(format_args!(
  30. "Default group has {} rows \n",
  31. self.default_group.rows.len()
  32. ));
  33. Ok(())
  34. }
  35. }
  36. pub struct GroupContext<C> {
  37. view_id: String,
  38. pub configuration: Arc<GroupConfigurationRevision>,
  39. configuration_content: PhantomData<C>,
  40. field_rev: Arc<FieldRevision>,
  41. groups_map: IndexMap<String, Group>,
  42. /// default_group is used to store the rows that don't belong to any groups.
  43. default_group: Group,
  44. writer: Arc<dyn GroupConfigurationWriter>,
  45. }
  46. impl<C> GroupContext<C>
  47. where
  48. C: GroupConfigurationContentSerde,
  49. {
  50. #[tracing::instrument(level = "trace", skip_all, err)]
  51. pub async fn new(
  52. view_id: String,
  53. field_rev: Arc<FieldRevision>,
  54. reader: Arc<dyn GroupConfigurationReader>,
  55. writer: Arc<dyn GroupConfigurationWriter>,
  56. ) -> FlowyResult<Self> {
  57. let default_group_id = format!("{}_default_group", view_id);
  58. let default_group = Group {
  59. id: default_group_id,
  60. field_id: field_rev.id.clone(),
  61. name: format!("No {}", field_rev.name),
  62. is_default: true,
  63. is_visible: true,
  64. rows: vec![],
  65. filter_content: "".to_string(),
  66. };
  67. let configuration = match reader.get_configuration(field_rev.clone()).await {
  68. None => {
  69. let default_configuration = default_group_configuration(&field_rev);
  70. writer
  71. .save_configuration(&field_rev.id, field_rev.ty, default_configuration.clone())
  72. .await?;
  73. Arc::new(default_configuration)
  74. }
  75. Some(configuration) => configuration,
  76. };
  77. // let configuration = C::from_configuration_content(&configuration_rev.content)?;
  78. Ok(Self {
  79. view_id,
  80. field_rev,
  81. groups_map: IndexMap::new(),
  82. default_group,
  83. writer,
  84. configuration,
  85. configuration_content: PhantomData,
  86. })
  87. }
  88. /// Returns the groups without the default group
  89. pub(crate) fn concrete_groups(&self) -> Vec<&Group> {
  90. self.groups_map.values().collect()
  91. }
  92. /// Returns the all the groups that contain the default group.
  93. pub(crate) fn clone_groups(&self) -> Vec<Group> {
  94. let mut groups: Vec<Group> = self.groups_map.values().cloned().collect();
  95. groups.push(self.default_group.clone());
  96. groups
  97. }
  98. /// Iterate mut the groups. The default group will be the last one that get mutated.
  99. pub(crate) fn iter_mut_groups(&mut self, mut each: impl FnMut(&mut Group)) {
  100. self.groups_map.iter_mut().for_each(|(_, group)| {
  101. each(group);
  102. });
  103. each(&mut self.default_group);
  104. }
  105. pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> {
  106. let from_index = self.groups_map.get_index_of(from_id);
  107. let to_index = self.groups_map.get_index_of(to_id);
  108. match (from_index, to_index) {
  109. (Some(from_index), Some(to_index)) => {
  110. self.groups_map.swap_indices(from_index, to_index);
  111. self.mut_configuration(|configuration| {
  112. let from_index = configuration.groups.iter().position(|group| group.id == from_id);
  113. let to_index = configuration.groups.iter().position(|group| group.id == to_id);
  114. if let (Some(from), Some(to)) = (from_index, to_index) {
  115. configuration.groups.swap(from, to);
  116. }
  117. true
  118. })?;
  119. Ok(())
  120. }
  121. _ => Err(FlowyError::out_of_bounds()),
  122. }
  123. }
  124. pub(crate) fn init_group_revs(
  125. &mut self,
  126. generated_groups: Vec<GeneratedGroup>,
  127. ) -> FlowyResult<Option<GroupViewChangesetPB>> {
  128. let mut new_groups = vec![];
  129. let mut filter_content_map = HashMap::new();
  130. generated_groups.into_iter().for_each(|generate_group| {
  131. filter_content_map.insert(generate_group.group_rev.id.clone(), generate_group.filter_content);
  132. new_groups.push(generate_group.group_rev);
  133. });
  134. let MergeGroupResult {
  135. mut all_group_revs,
  136. new_group_revs,
  137. updated_group_revs: _,
  138. deleted_group_revs,
  139. } = merge_groups(&self.configuration.groups, new_groups);
  140. let deleted_group_ids = deleted_group_revs
  141. .iter()
  142. .map(|group_rev| group_rev.id)
  143. .collect::<Vec<String>>();
  144. self.mut_configuration(|configuration| {
  145. let mut is_changed = false;
  146. if !deleted_group_ids.is_empty() {
  147. configuration
  148. .groups
  149. .retain(|group| !deleted_group_ids.contains(&group.id));
  150. is_changed = true;
  151. }
  152. for mut group_rev in &mut all_group_revs {
  153. match configuration
  154. .groups
  155. .iter()
  156. .position(|old_group_rev| old_group_rev.id == group_rev.id)
  157. {
  158. None => {
  159. configuration.groups.push(group_rev.clone());
  160. is_changed = true;
  161. }
  162. Some(pos) => {
  163. let mut old_group = configuration.groups.remove(pos);
  164. // Update the group configuration base on the GroupRevision
  165. group_rev.visible = old_group.visible;
  166. // Take the GroupRevision if the name has changed
  167. if is_group_changed(&group_rev, &old_group) {
  168. old_group.name = group_rev.name.clone();
  169. is_changed = true;
  170. configuration.groups.insert(pos, old_group);
  171. }
  172. }
  173. }
  174. }
  175. is_changed
  176. })?;
  177. debug_assert_eq!(filter_content_map.len(), all_group_revs.len());
  178. all_group_revs.into_iter().for_each(|group_rev| {
  179. if let Some(filter_content) = filter_content_map.get(&group_rev.id) {
  180. let group = Group::new(
  181. group_rev.id,
  182. self.field_rev.id.clone(),
  183. group_rev.name,
  184. filter_content.clone(),
  185. );
  186. self.groups_map.insert(group.id.clone(), group);
  187. }
  188. });
  189. let new_groups = new_group_revs
  190. .into_iter()
  191. .map(|group_rev| {
  192. if let Some(filter_content) = filter_content_map.get(&group_rev.id) {
  193. let group = Group::new(
  194. group_rev.id,
  195. self.field_rev.id.clone(),
  196. group_rev.name,
  197. filter_content.clone(),
  198. );
  199. GroupPB::from(group)
  200. }
  201. })
  202. .collect();
  203. let changeset = GroupViewChangesetPB {
  204. view_id,
  205. new_groups,
  206. deleted_groups: deleted_group_ids,
  207. update_groups: vec![],
  208. inserted_groups: vec![],
  209. };
  210. tracing::trace!("Group changeset: {:?}", changeset);
  211. if changeset.is_empty() {
  212. Ok(None)
  213. } else {
  214. Ok(Some(changeset))
  215. }
  216. }
  217. #[allow(dead_code)]
  218. pub(crate) async fn hide_group(&mut self, group_id: &str) -> FlowyResult<()> {
  219. self.mut_group_rev(group_id, |group_rev| {
  220. group_rev.visible = false;
  221. })?;
  222. Ok(())
  223. }
  224. #[allow(dead_code)]
  225. pub(crate) async fn show_group(&mut self, group_id: &str) -> FlowyResult<()> {
  226. self.mut_group_rev(group_id, |group_rev| {
  227. group_rev.visible = true;
  228. })?;
  229. Ok(())
  230. }
  231. pub(crate) fn get_mut_default_group(&mut self) -> &mut Group {
  232. &mut self.default_group
  233. }
  234. pub(crate) fn get_mut_group(&mut self, group_id: &str) -> Option<&mut Group> {
  235. self.groups_map.get_mut(group_id)
  236. }
  237. // Returns the index and group specified by the group_id
  238. pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &Group)> {
  239. match (self.groups_map.get_index_of(group_id), self.groups_map.get(group_id)) {
  240. (Some(index), Some(group)) => Some((index, group)),
  241. _ => None,
  242. }
  243. }
  244. pub fn save_configuration(&self) -> FlowyResult<()> {
  245. let configuration = (&*self.configuration).clone();
  246. let writer = self.writer.clone();
  247. let field_id = self.field_rev.id.clone();
  248. let field_type = self.field_rev.ty;
  249. tokio::spawn(async move {
  250. match writer.save_configuration(&field_id, field_type, configuration).await {
  251. Ok(_) => {}
  252. Err(e) => {
  253. tracing::error!("Save group configuration failed: {}", e);
  254. }
  255. }
  256. });
  257. Ok(())
  258. }
  259. fn mut_configuration(
  260. &mut self,
  261. mut_configuration_fn: impl FnOnce(&mut GroupConfigurationRevision) -> bool,
  262. ) -> FlowyResult<()> {
  263. let configuration = Arc::make_mut(&mut self.configuration);
  264. let is_changed = mut_configuration_fn(configuration);
  265. if is_changed {
  266. let _ = self.save_configuration()?;
  267. }
  268. Ok(())
  269. }
  270. fn mut_group_rev(&mut self, group_id: &str, mut_groups_fn: impl Fn(&mut GroupRevision)) -> FlowyResult<()> {
  271. self.mut_configuration(|configuration| {
  272. match configuration.groups.iter_mut().find(|group| group.id == group_id) {
  273. None => false,
  274. Some(group_rev) => {
  275. mut_groups_fn(group_rev);
  276. true
  277. }
  278. }
  279. })
  280. }
  281. }
  282. fn merge_groups(old_groups: &[GroupRevision], new_groups: Vec<GroupRevision>) -> MergeGroupResult {
  283. let mut merge_result = MergeGroupResult::new();
  284. if old_groups.is_empty() {
  285. merge_result.all_group_revs = new_groups;
  286. return merge_result;
  287. }
  288. // group_map is a helper map is used to filter out the new groups.
  289. let mut new_group_map: IndexMap<String, GroupRevision> = IndexMap::new();
  290. new_groups.into_iter().for_each(|group_rev| {
  291. new_group_map.insert(group_rev.id.clone(), group_rev);
  292. });
  293. // The group is ordered in old groups. Add them before adding the new groups
  294. for old in old_groups {
  295. if let Some(new) = new_group_map.remove(&old.id) {
  296. merge_result.all_group_revs.push(new.clone());
  297. if is_group_changed(&new, old) {
  298. merge_result.updated_group_revs.push(new);
  299. }
  300. } else {
  301. merge_result.deleted_group_revs.push(old.clone());
  302. }
  303. }
  304. // Find out the new groups
  305. let new_groups = new_group_map.into_values();
  306. for (_, group) in new_groups.into_iter().enumerate() {
  307. merge_result.all_group_revs.push(group.clone());
  308. merge_result.new_group_revs.push(group);
  309. }
  310. merge_result
  311. }
  312. fn is_group_changed(new: &GroupRevision, old: &GroupRevision) -> bool {
  313. if new.name != old.name {
  314. return true;
  315. }
  316. false
  317. }
  318. struct MergeGroupResult {
  319. // Contains the new groups and the updated groups
  320. all_group_revs: Vec<GroupRevision>,
  321. new_group_revs: Vec<GroupRevision>,
  322. updated_group_revs: Vec<GroupRevision>,
  323. deleted_group_revs: Vec<GroupRevision>,
  324. }
  325. impl MergeGroupResult {
  326. fn new() -> Self {
  327. Self {
  328. all_group_revs: vec![],
  329. new_group_revs: vec![],
  330. updated_group_revs: vec![],
  331. deleted_group_revs: vec![],
  332. }
  333. }
  334. }