controller.rs 13 KB

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