controller.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB};
  2. use crate::services::cell::{decode_any_cell_data, CellBytesParser, CellDataIsEmpty};
  3. use crate::services::group::action::{GroupControllerCustomActions, GroupControllerSharedActions};
  4. use crate::services::group::configuration::GroupContext;
  5. use crate::services::group::entities::Group;
  6. use flowy_error::FlowyResult;
  7. use grid_rev_model::{
  8. FieldRevision, GroupConfigurationContentSerde, GroupRevision, RowChangeset, RowRevision, TypeOptionDataDeserializer,
  9. };
  10. use std::marker::PhantomData;
  11. use std::sync::Arc;
  12. /// The [GroupController] trait defines the group actions, including create/delete/move items
  13. /// For example, the group will insert a item if the one of the new [RowRevision]'s [CellRevision]s
  14. /// content match the group filter.
  15. ///
  16. /// Different [FieldType] has a different controller that implements the [GroupController] trait.
  17. /// If the [FieldType] doesn't implement its group controller, then the [DefaultGroupController] will
  18. /// be used.
  19. ///
  20. pub trait GroupController: GroupControllerSharedActions + Send + Sync {
  21. fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
  22. fn did_create_row(&mut self, row_pb: &RowPB, group_id: &str);
  23. }
  24. /// The [GroupGenerator] trait is used to generate the groups for different [FieldType]
  25. pub trait GroupGenerator {
  26. type Context;
  27. type TypeOptionType;
  28. fn generate_groups(
  29. field_rev: &FieldRevision,
  30. group_ctx: &Self::Context,
  31. type_option: &Option<Self::TypeOptionType>,
  32. ) -> GeneratedGroupContext;
  33. }
  34. pub struct GeneratedGroupContext {
  35. pub no_status_group: Option<GroupRevision>,
  36. pub group_configs: Vec<GeneratedGroupConfig>,
  37. }
  38. pub struct GeneratedGroupConfig {
  39. pub group_rev: GroupRevision,
  40. pub filter_content: String,
  41. }
  42. pub struct MoveGroupRowContext<'a> {
  43. pub row_rev: &'a RowRevision,
  44. pub row_changeset: &'a mut RowChangeset,
  45. pub field_rev: &'a FieldRevision,
  46. pub to_group_id: &'a str,
  47. pub to_row_id: Option<String>,
  48. }
  49. /// C: represents the group configuration that impl [GroupConfigurationSerde]
  50. /// T: the type-option data deserializer that impl [TypeOptionDataDeserializer]
  51. /// G: the group generator, [GroupGenerator]
  52. /// P: the parser that impl [CellBytesParser] for the CellBytes
  53. pub struct GenericGroupController<C, T, G, P> {
  54. pub field_id: String,
  55. pub type_option: Option<T>,
  56. pub group_ctx: GroupContext<C>,
  57. group_action_phantom: PhantomData<G>,
  58. cell_parser_phantom: PhantomData<P>,
  59. }
  60. impl<C, T, G, P> GenericGroupController<C, T, G, P>
  61. where
  62. C: GroupConfigurationContentSerde,
  63. T: TypeOptionDataDeserializer,
  64. G: GroupGenerator<Context = GroupContext<C>, TypeOptionType = T>,
  65. {
  66. pub async fn new(field_rev: &Arc<FieldRevision>, mut configuration: GroupContext<C>) -> FlowyResult<Self> {
  67. let type_option = field_rev.get_type_option::<T>(field_rev.ty);
  68. let generated_group_context = G::generate_groups(field_rev, &configuration, &type_option);
  69. let _ = configuration.init_groups(generated_group_context)?;
  70. Ok(Self {
  71. field_id: field_rev.id.clone(),
  72. type_option,
  73. group_ctx: configuration,
  74. group_action_phantom: PhantomData,
  75. cell_parser_phantom: PhantomData,
  76. })
  77. }
  78. // https://stackoverflow.com/questions/69413164/how-to-fix-this-clippy-warning-needless-collect
  79. #[allow(clippy::needless_collect)]
  80. fn update_default_group(
  81. &mut self,
  82. row_rev: &RowRevision,
  83. other_group_changesets: &[GroupChangesetPB],
  84. ) -> Option<GroupChangesetPB> {
  85. let default_group = self.group_ctx.get_mut_no_status_group()?;
  86. // [other_group_inserted_row] contains all the inserted rows except the default group.
  87. let other_group_inserted_row = other_group_changesets
  88. .iter()
  89. .flat_map(|changeset| &changeset.inserted_rows)
  90. .collect::<Vec<&InsertedRowPB>>();
  91. // Calculate the inserted_rows of the default_group
  92. let default_group_inserted_row = other_group_changesets
  93. .iter()
  94. .flat_map(|changeset| &changeset.deleted_rows)
  95. .cloned()
  96. .filter(|row_id| {
  97. // if the [other_group_inserted_row] contains the row_id of the row
  98. // which means the row should not move to the default group.
  99. !other_group_inserted_row
  100. .iter()
  101. .any(|inserted_row| &inserted_row.row.id == row_id)
  102. })
  103. .collect::<Vec<String>>();
  104. let mut changeset = GroupChangesetPB::new(default_group.id.clone());
  105. if !default_group_inserted_row.is_empty() {
  106. changeset.inserted_rows.push(InsertedRowPB::new(row_rev.into()));
  107. default_group.add_row(row_rev.into());
  108. }
  109. // [other_group_delete_rows] contains all the deleted rows except the default group.
  110. let other_group_delete_rows: Vec<String> = other_group_changesets
  111. .iter()
  112. .flat_map(|changeset| &changeset.deleted_rows)
  113. .cloned()
  114. .collect();
  115. let default_group_deleted_rows = other_group_changesets
  116. .iter()
  117. .flat_map(|changeset| &changeset.inserted_rows)
  118. .filter(|inserted_row| {
  119. // if the [other_group_delete_rows] contain the inserted_row, which means this row should move
  120. // out from the default_group.
  121. let inserted_row_id = &inserted_row.row.id;
  122. !other_group_delete_rows.iter().any(|row_id| inserted_row_id == row_id)
  123. })
  124. .collect::<Vec<&InsertedRowPB>>();
  125. let mut deleted_row_ids = vec![];
  126. for row in &default_group.rows {
  127. if default_group_deleted_rows
  128. .iter()
  129. .any(|deleted_row| deleted_row.row.id == row.id)
  130. {
  131. deleted_row_ids.push(row.id.clone());
  132. }
  133. }
  134. default_group.rows.retain(|row| !deleted_row_ids.contains(&row.id));
  135. changeset.deleted_rows.extend(deleted_row_ids);
  136. Some(changeset)
  137. }
  138. }
  139. impl<C, T, G, P> GroupControllerSharedActions for GenericGroupController<C, T, G, P>
  140. where
  141. P: CellBytesParser,
  142. C: GroupConfigurationContentSerde,
  143. T: TypeOptionDataDeserializer,
  144. G: GroupGenerator<Context = GroupContext<C>, TypeOptionType = T>,
  145. Self: GroupControllerCustomActions<CellDataType = P::Object>,
  146. {
  147. fn field_id(&self) -> &str {
  148. &self.field_id
  149. }
  150. fn groups(&self) -> Vec<&Group> {
  151. self.group_ctx.groups()
  152. }
  153. fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
  154. let group = self.group_ctx.get_group(group_id)?;
  155. Some((group.0, group.1.clone()))
  156. }
  157. #[tracing::instrument(level = "trace", skip_all, fields(row_count=%row_revs.len(), group_result))]
  158. fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
  159. for row_rev in row_revs {
  160. let cell_rev = match row_rev.cells.get(&self.field_id) {
  161. None => self.default_cell_rev(),
  162. Some(cell_rev) => Some(cell_rev.clone()),
  163. };
  164. if let Some(cell_rev) = cell_rev {
  165. let mut grouped_rows: Vec<GroupedRow> = vec![];
  166. let cell_bytes = decode_any_cell_data(cell_rev.data, field_rev).1;
  167. let cell_data = cell_bytes.parser::<P>()?;
  168. for group in self.group_ctx.groups() {
  169. if self.can_group(&group.filter_content, &cell_data) {
  170. grouped_rows.push(GroupedRow {
  171. row: row_rev.into(),
  172. group_id: group.id.clone(),
  173. });
  174. }
  175. }
  176. if !grouped_rows.is_empty() {
  177. for group_row in grouped_rows {
  178. if let Some(group) = self.group_ctx.get_mut_group(&group_row.group_id) {
  179. group.add_row(group_row.row);
  180. }
  181. }
  182. continue;
  183. }
  184. }
  185. match self.group_ctx.get_mut_no_status_group() {
  186. None => {}
  187. Some(default_group) => default_group.add_row(row_rev.into()),
  188. }
  189. }
  190. tracing::Span::current().record("group_result", &format!("{},", self.group_ctx,).as_str());
  191. Ok(())
  192. }
  193. fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> {
  194. self.group_ctx.move_group(from_group_id, to_group_id)
  195. }
  196. fn did_update_group_row(
  197. &mut self,
  198. row_rev: &RowRevision,
  199. field_rev: &FieldRevision,
  200. ) -> FlowyResult<Vec<GroupChangesetPB>> {
  201. if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
  202. let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
  203. let cell_data = cell_bytes.parser::<P>()?;
  204. let mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data);
  205. if let Some(default_group_changeset) = self.update_default_group(row_rev, &changesets) {
  206. tracing::trace!("default_group_changeset: {}", default_group_changeset);
  207. if !default_group_changeset.is_empty() {
  208. changesets.push(default_group_changeset);
  209. }
  210. }
  211. Ok(changesets)
  212. } else {
  213. Ok(vec![])
  214. }
  215. }
  216. fn did_delete_delete_row(
  217. &mut self,
  218. row_rev: &RowRevision,
  219. field_rev: &FieldRevision,
  220. ) -> FlowyResult<Vec<GroupChangesetPB>> {
  221. // if the cell_rev is none, then the row must in the default group.
  222. if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
  223. let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
  224. let cell_data = cell_bytes.parser::<P>()?;
  225. if !cell_data.is_empty() {
  226. tracing::error!("did_delete_delete_row {:?}", cell_rev.data);
  227. return Ok(self.delete_row(row_rev, &cell_data));
  228. }
  229. }
  230. match self.group_ctx.get_no_status_group() {
  231. None => {
  232. tracing::error!("Unexpected None value. It should have the no status group");
  233. Ok(vec![])
  234. }
  235. Some(no_status_group) => {
  236. if !no_status_group.contains_row(&row_rev.id) {
  237. tracing::error!("The row: {} should be in the no status group", row_rev.id);
  238. }
  239. Ok(vec![GroupChangesetPB::delete(
  240. no_status_group.id.clone(),
  241. vec![row_rev.id.clone()],
  242. )])
  243. }
  244. }
  245. }
  246. #[tracing::instrument(level = "trace", skip_all, err)]
  247. fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupChangesetPB>> {
  248. let cell_rev = match context.row_rev.cells.get(&self.field_id) {
  249. Some(cell_rev) => Some(cell_rev.clone()),
  250. None => self.default_cell_rev(),
  251. };
  252. if let Some(cell_rev) = cell_rev {
  253. let cell_bytes = decode_any_cell_data(cell_rev.data, context.field_rev).1;
  254. let cell_data = cell_bytes.parser::<P>()?;
  255. Ok(self.move_row(&cell_data, context))
  256. } else {
  257. tracing::warn!("Unexpected moving group row, changes should not be empty");
  258. Ok(vec![])
  259. }
  260. }
  261. fn did_update_group_field(&mut self, _field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
  262. Ok(None)
  263. }
  264. }
  265. struct GroupedRow {
  266. row: RowPB,
  267. group_id: String,
  268. }