configuration.rs 11 KB

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