grid_revision_pad.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. use crate::entities::revision::{md5, RepeatedRevision, Revision};
  2. use crate::errors::{internal_error, CollaborateError, CollaborateResult};
  3. use crate::util::{cal_diff, make_delta_from_revisions};
  4. use bytes::Bytes;
  5. use flowy_grid_data_model::entities::{FieldChangesetParams, FieldOrder};
  6. use flowy_grid_data_model::entities::{FieldType, GridSettingChangesetParams};
  7. use flowy_grid_data_model::revision::{
  8. gen_block_id, gen_grid_filter_id, gen_grid_group_id, gen_grid_id, gen_grid_sort_id, FieldRevision,
  9. GridBlockRevision, GridBlockRevisionChangeset, GridFilterRevision, GridGroupRevision, GridLayoutRevision,
  10. GridRevision, GridSettingRevision, GridSortRevision,
  11. };
  12. use lib_infra::util::move_vec_element;
  13. use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
  14. use std::collections::HashMap;
  15. use std::sync::Arc;
  16. pub type GridRevisionDelta = PlainTextDelta;
  17. pub type GridRevisionDeltaBuilder = PlainTextDeltaBuilder;
  18. pub struct GridRevisionPad {
  19. pub(crate) grid_rev: Arc<GridRevision>,
  20. pub(crate) delta: GridRevisionDelta,
  21. }
  22. pub trait JsonDeserializer {
  23. fn deserialize(&self, type_option_data: Vec<u8>) -> CollaborateResult<String>;
  24. }
  25. impl GridRevisionPad {
  26. pub async fn duplicate_grid_meta(&self) -> (Vec<FieldRevision>, Vec<GridBlockRevision>) {
  27. let fields = self.grid_rev.fields.to_vec();
  28. let blocks = self
  29. .grid_rev
  30. .blocks
  31. .iter()
  32. .map(|block| {
  33. let mut duplicated_block = block.clone();
  34. duplicated_block.block_id = gen_block_id();
  35. duplicated_block
  36. })
  37. .collect::<Vec<GridBlockRevision>>();
  38. (fields, blocks)
  39. }
  40. pub fn from_delta(delta: GridRevisionDelta) -> CollaborateResult<Self> {
  41. let s = delta.to_str()?;
  42. let grid: GridRevision = serde_json::from_str(&s)
  43. .map_err(|e| CollaborateError::internal().context(format!("Deserialize delta to grid failed: {}", e)))?;
  44. Ok(Self {
  45. grid_rev: Arc::new(grid),
  46. delta,
  47. })
  48. }
  49. pub fn from_revisions(_grid_id: &str, revisions: Vec<Revision>) -> CollaborateResult<Self> {
  50. let grid_delta: GridRevisionDelta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
  51. Self::from_delta(grid_delta)
  52. }
  53. #[tracing::instrument(level = "debug", skip_all, err)]
  54. pub fn create_field_rev(
  55. &mut self,
  56. new_field_rev: FieldRevision,
  57. start_field_id: Option<String>,
  58. ) -> CollaborateResult<Option<GridChangeset>> {
  59. self.modify_grid(|grid_meta| {
  60. // Check if the field exists or not
  61. if grid_meta
  62. .fields
  63. .iter()
  64. .any(|field_rev| field_rev.id == new_field_rev.id)
  65. {
  66. tracing::error!("Duplicate grid field");
  67. return Ok(None);
  68. }
  69. let insert_index = match start_field_id {
  70. None => None,
  71. Some(start_field_id) => grid_meta.fields.iter().position(|field| field.id == start_field_id),
  72. };
  73. match insert_index {
  74. None => grid_meta.fields.push(new_field_rev),
  75. Some(index) => grid_meta.fields.insert(index, new_field_rev),
  76. }
  77. Ok(Some(()))
  78. })
  79. }
  80. pub fn delete_field_rev(&mut self, field_id: &str) -> CollaborateResult<Option<GridChangeset>> {
  81. self.modify_grid(
  82. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
  83. None => Ok(None),
  84. Some(index) => {
  85. grid_meta.fields.remove(index);
  86. Ok(Some(()))
  87. }
  88. },
  89. )
  90. }
  91. pub fn duplicate_field_rev(
  92. &mut self,
  93. field_id: &str,
  94. duplicated_field_id: &str,
  95. ) -> CollaborateResult<Option<GridChangeset>> {
  96. self.modify_grid(
  97. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
  98. None => Ok(None),
  99. Some(index) => {
  100. let mut duplicate_field_rev = grid_meta.fields[index].clone();
  101. duplicate_field_rev.id = duplicated_field_id.to_string();
  102. duplicate_field_rev.name = format!("{} (copy)", duplicate_field_rev.name);
  103. grid_meta.fields.insert(index + 1, duplicate_field_rev);
  104. Ok(Some(()))
  105. }
  106. },
  107. )
  108. }
  109. pub fn switch_to_field<B>(
  110. &mut self,
  111. field_id: &str,
  112. field_type: FieldType,
  113. type_option_json_builder: B,
  114. ) -> CollaborateResult<Option<GridChangeset>>
  115. where
  116. B: FnOnce(&FieldType) -> String,
  117. {
  118. self.modify_grid(|grid_meta| {
  119. //
  120. match grid_meta.fields.iter_mut().find(|field_rev| field_rev.id == field_id) {
  121. None => {
  122. tracing::warn!("Can not find the field with id: {}", field_id);
  123. Ok(None)
  124. }
  125. Some(field_rev) => {
  126. if field_rev.get_type_option_str(&field_type).is_none() {
  127. let type_option_json = type_option_json_builder(&field_type);
  128. field_rev.insert_type_option_str(&field_type, type_option_json);
  129. }
  130. field_rev.field_type = field_type;
  131. Ok(Some(()))
  132. }
  133. }
  134. })
  135. }
  136. pub fn update_field_rev<T: JsonDeserializer>(
  137. &mut self,
  138. changeset: FieldChangesetParams,
  139. deserializer: T,
  140. ) -> CollaborateResult<Option<GridChangeset>> {
  141. let field_id = changeset.field_id.clone();
  142. self.modify_field(&field_id, |field| {
  143. let mut is_changed = None;
  144. if let Some(name) = changeset.name {
  145. field.name = name;
  146. is_changed = Some(())
  147. }
  148. if let Some(desc) = changeset.desc {
  149. field.desc = desc;
  150. is_changed = Some(())
  151. }
  152. if let Some(field_type) = changeset.field_type {
  153. field.field_type = field_type;
  154. is_changed = Some(())
  155. }
  156. if let Some(frozen) = changeset.frozen {
  157. field.frozen = frozen;
  158. is_changed = Some(())
  159. }
  160. if let Some(visibility) = changeset.visibility {
  161. field.visibility = visibility;
  162. is_changed = Some(())
  163. }
  164. if let Some(width) = changeset.width {
  165. field.width = width;
  166. is_changed = Some(())
  167. }
  168. if let Some(type_option_data) = changeset.type_option_data {
  169. match deserializer.deserialize(type_option_data) {
  170. Ok(json_str) => {
  171. let field_type = field.field_type.clone();
  172. field.insert_type_option_str(&field_type, json_str);
  173. is_changed = Some(())
  174. }
  175. Err(err) => {
  176. tracing::error!("Deserialize data to type option json failed: {}", err);
  177. }
  178. }
  179. }
  180. Ok(is_changed)
  181. })
  182. }
  183. pub fn get_field_rev(&self, field_id: &str) -> Option<(usize, &FieldRevision)> {
  184. self.grid_rev
  185. .fields
  186. .iter()
  187. .enumerate()
  188. .find(|(_, field)| field.id == field_id)
  189. }
  190. pub fn replace_field_rev(&mut self, field_rev: FieldRevision) -> CollaborateResult<Option<GridChangeset>> {
  191. self.modify_grid(
  192. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_rev.id) {
  193. None => Ok(None),
  194. Some(index) => {
  195. grid_meta.fields.remove(index);
  196. grid_meta.fields.insert(index, field_rev);
  197. Ok(Some(()))
  198. }
  199. },
  200. )
  201. }
  202. pub fn move_field(
  203. &mut self,
  204. field_id: &str,
  205. from_index: usize,
  206. to_index: usize,
  207. ) -> CollaborateResult<Option<GridChangeset>> {
  208. self.modify_grid(|grid_meta| {
  209. match move_vec_element(
  210. &mut grid_meta.fields,
  211. |field| field.id == field_id,
  212. from_index,
  213. to_index,
  214. )
  215. .map_err(internal_error)?
  216. {
  217. true => Ok(Some(())),
  218. false => Ok(None),
  219. }
  220. })
  221. }
  222. pub fn contain_field(&self, field_id: &str) -> bool {
  223. self.grid_rev.fields.iter().any(|field| field.id == field_id)
  224. }
  225. pub fn get_field_orders(&self) -> Vec<FieldOrder> {
  226. self.grid_rev.fields.iter().map(FieldOrder::from).collect()
  227. }
  228. pub fn get_field_revs(&self, field_orders: Option<Vec<FieldOrder>>) -> CollaborateResult<Vec<FieldRevision>> {
  229. match field_orders {
  230. None => Ok(self.grid_rev.fields.clone()),
  231. Some(field_orders) => {
  232. let field_by_field_id = self
  233. .grid_rev
  234. .fields
  235. .iter()
  236. .map(|field| (&field.id, field))
  237. .collect::<HashMap<&String, &FieldRevision>>();
  238. let fields = field_orders
  239. .iter()
  240. .flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
  241. None => {
  242. tracing::error!("Can't find the field with id: {}", field_order.field_id);
  243. None
  244. }
  245. Some(field) => Some((*field).clone()),
  246. })
  247. .collect::<Vec<FieldRevision>>();
  248. Ok(fields)
  249. }
  250. }
  251. }
  252. pub fn create_block_rev(&mut self, block: GridBlockRevision) -> CollaborateResult<Option<GridChangeset>> {
  253. self.modify_grid(|grid_meta| {
  254. if grid_meta.blocks.iter().any(|b| b.block_id == block.block_id) {
  255. tracing::warn!("Duplicate grid block");
  256. Ok(None)
  257. } else {
  258. match grid_meta.blocks.last() {
  259. None => grid_meta.blocks.push(block),
  260. Some(last_block) => {
  261. if last_block.start_row_index > block.start_row_index
  262. && last_block.len() > block.start_row_index
  263. {
  264. let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string();
  265. return Err(CollaborateError::internal().context(msg))
  266. }
  267. grid_meta.blocks.push(block);
  268. }
  269. }
  270. Ok(Some(()))
  271. }
  272. })
  273. }
  274. pub fn get_block_revs(&self) -> Vec<GridBlockRevision> {
  275. self.grid_rev.blocks.clone()
  276. }
  277. pub fn update_block_rev(
  278. &mut self,
  279. changeset: GridBlockRevisionChangeset,
  280. ) -> CollaborateResult<Option<GridChangeset>> {
  281. let block_id = changeset.block_id.clone();
  282. self.modify_block(&block_id, |block| {
  283. let mut is_changed = None;
  284. if let Some(row_count) = changeset.row_count {
  285. block.row_count = row_count;
  286. is_changed = Some(());
  287. }
  288. if let Some(start_row_index) = changeset.start_row_index {
  289. block.start_row_index = start_row_index;
  290. is_changed = Some(());
  291. }
  292. Ok(is_changed)
  293. })
  294. }
  295. pub fn get_grid_setting_rev(&self) -> &GridSettingRevision {
  296. &self.grid_rev.setting
  297. }
  298. pub fn update_grid_setting_rev(
  299. &mut self,
  300. changeset: GridSettingChangesetParams,
  301. ) -> CollaborateResult<Option<GridChangeset>> {
  302. self.modify_grid(|grid_rev| {
  303. let mut is_changed = None;
  304. let layout_rev: GridLayoutRevision = changeset.layout_type.into();
  305. if let Some(params) = changeset.insert_filter {
  306. let rev = GridFilterRevision {
  307. id: gen_grid_filter_id(),
  308. field_id: params.field_id,
  309. condition: params.condition,
  310. content: params.content,
  311. };
  312. grid_rev
  313. .setting
  314. .filter
  315. .entry(layout_rev.clone())
  316. .or_insert_with(std::vec::Vec::new)
  317. .push(rev);
  318. is_changed = Some(())
  319. }
  320. if let Some(delete_filter_id) = changeset.delete_filter {
  321. match grid_rev.setting.filter.get_mut(&layout_rev) {
  322. Some(filters) => filters.retain(|filter| filter.id != delete_filter_id),
  323. None => {}
  324. }
  325. }
  326. if let Some(params) = changeset.insert_group {
  327. let rev = GridGroupRevision {
  328. id: gen_grid_group_id(),
  329. field_id: params.field_id,
  330. sub_field_id: params.sub_field_id,
  331. };
  332. grid_rev
  333. .setting
  334. .group
  335. .entry(layout_rev.clone())
  336. .or_insert_with(std::vec::Vec::new)
  337. .push(rev);
  338. is_changed = Some(())
  339. }
  340. if let Some(delete_group_id) = changeset.delete_group {
  341. match grid_rev.setting.group.get_mut(&layout_rev) {
  342. Some(groups) => groups.retain(|group| group.id != delete_group_id),
  343. None => {}
  344. }
  345. }
  346. if let Some(sort) = changeset.insert_sort {
  347. let rev = GridSortRevision {
  348. id: gen_grid_sort_id(),
  349. field_id: sort.field_id,
  350. };
  351. grid_rev
  352. .setting
  353. .sort
  354. .entry(layout_rev.clone())
  355. .or_insert_with(std::vec::Vec::new)
  356. .push(rev);
  357. is_changed = Some(())
  358. }
  359. if let Some(delete_sort_id) = changeset.delete_sort {
  360. match grid_rev.setting.sort.get_mut(&layout_rev) {
  361. Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id),
  362. None => {}
  363. }
  364. }
  365. Ok(is_changed)
  366. })
  367. }
  368. pub fn md5(&self) -> String {
  369. md5(&self.delta.to_delta_bytes())
  370. }
  371. pub fn delta_str(&self) -> String {
  372. self.delta.to_delta_str()
  373. }
  374. pub fn delta_bytes(&self) -> Bytes {
  375. self.delta.to_delta_bytes()
  376. }
  377. pub fn fields(&self) -> &[FieldRevision] {
  378. &self.grid_rev.fields
  379. }
  380. fn modify_grid<F>(&mut self, f: F) -> CollaborateResult<Option<GridChangeset>>
  381. where
  382. F: FnOnce(&mut GridRevision) -> CollaborateResult<Option<()>>,
  383. {
  384. let cloned_grid = self.grid_rev.clone();
  385. match f(Arc::make_mut(&mut self.grid_rev))? {
  386. None => Ok(None),
  387. Some(_) => {
  388. let old = json_from_grid(&cloned_grid)?;
  389. let new = json_from_grid(&self.grid_rev)?;
  390. match cal_diff::<PlainTextAttributes>(old, new) {
  391. None => Ok(None),
  392. Some(delta) => {
  393. self.delta = self.delta.compose(&delta)?;
  394. Ok(Some(GridChangeset { delta, md5: self.md5() }))
  395. }
  396. }
  397. }
  398. }
  399. }
  400. fn modify_block<F>(&mut self, block_id: &str, f: F) -> CollaborateResult<Option<GridChangeset>>
  401. where
  402. F: FnOnce(&mut GridBlockRevision) -> CollaborateResult<Option<()>>,
  403. {
  404. self.modify_grid(
  405. |grid_rev| match grid_rev.blocks.iter().position(|block| block.block_id == block_id) {
  406. None => {
  407. tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id);
  408. Ok(None)
  409. }
  410. Some(index) => f(&mut grid_rev.blocks[index]),
  411. },
  412. )
  413. }
  414. fn modify_field<F>(&mut self, field_id: &str, f: F) -> CollaborateResult<Option<GridChangeset>>
  415. where
  416. F: FnOnce(&mut FieldRevision) -> CollaborateResult<Option<()>>,
  417. {
  418. self.modify_grid(
  419. |grid_rev| match grid_rev.fields.iter().position(|field| field.id == field_id) {
  420. None => {
  421. tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id);
  422. Ok(None)
  423. }
  424. Some(index) => f(&mut grid_rev.fields[index]),
  425. },
  426. )
  427. }
  428. }
  429. fn json_from_grid(grid: &Arc<GridRevision>) -> CollaborateResult<String> {
  430. let json = serde_json::to_string(grid)
  431. .map_err(|err| internal_error(format!("Serialize grid to json str failed. {:?}", err)))?;
  432. Ok(json)
  433. }
  434. pub struct GridChangeset {
  435. pub delta: GridRevisionDelta,
  436. /// md5: the md5 of the grid after applying the change.
  437. pub md5: String,
  438. }
  439. pub fn make_grid_delta(grid_rev: &GridRevision) -> GridRevisionDelta {
  440. let json = serde_json::to_string(&grid_rev).unwrap();
  441. PlainTextDeltaBuilder::new().insert(&json).build()
  442. }
  443. pub fn make_grid_revisions(user_id: &str, grid_rev: &GridRevision) -> RepeatedRevision {
  444. let delta = make_grid_delta(grid_rev);
  445. let bytes = delta.to_delta_bytes();
  446. let revision = Revision::initial_revision(user_id, &grid_rev.grid_id, bytes);
  447. revision.into()
  448. }
  449. impl std::default::Default for GridRevisionPad {
  450. fn default() -> Self {
  451. let grid = GridRevision::new(&gen_grid_id());
  452. let delta = make_grid_delta(&grid);
  453. GridRevisionPad {
  454. grid_rev: Arc::new(grid),
  455. delta,
  456. }
  457. }
  458. }