grid_meta_pad.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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::{
  6. FieldChangeset, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder,
  7. };
  8. use lib_infra::uuid;
  9. use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
  10. use std::collections::HashMap;
  11. use std::sync::Arc;
  12. pub type GridMetaDelta = PlainTextDelta;
  13. pub type GridDeltaBuilder = PlainTextDeltaBuilder;
  14. pub struct GridMetaPad {
  15. pub(crate) grid_meta: Arc<GridMeta>,
  16. pub(crate) delta: GridMetaDelta,
  17. }
  18. impl GridMetaPad {
  19. pub fn from_delta(delta: GridMetaDelta) -> CollaborateResult<Self> {
  20. let s = delta.to_str()?;
  21. let grid: GridMeta = serde_json::from_str(&s)
  22. .map_err(|e| CollaborateError::internal().context(format!("Deserialize delta to grid failed: {}", e)))?;
  23. Ok(Self {
  24. grid_meta: Arc::new(grid),
  25. delta,
  26. })
  27. }
  28. pub fn from_revisions(_grid_id: &str, revisions: Vec<Revision>) -> CollaborateResult<Self> {
  29. let grid_delta: GridMetaDelta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
  30. Self::from_delta(grid_delta)
  31. }
  32. pub fn create_field(&mut self, field_meta: FieldMeta) -> CollaborateResult<Option<GridChangeset>> {
  33. self.modify_grid(|grid| {
  34. if grid.fields.contains(&field_meta) {
  35. tracing::warn!("Duplicate grid field");
  36. Ok(None)
  37. } else {
  38. grid.fields.push(field_meta);
  39. Ok(Some(()))
  40. }
  41. })
  42. }
  43. pub fn delete_field(&mut self, field_id: &str) -> CollaborateResult<Option<GridChangeset>> {
  44. self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) {
  45. None => Ok(None),
  46. Some(index) => {
  47. grid.fields.remove(index);
  48. Ok(Some(()))
  49. }
  50. })
  51. }
  52. pub fn contain_field(&self, field_id: &str) -> bool {
  53. self.grid_meta.fields.iter().any(|field| field.id == field_id)
  54. }
  55. pub fn get_field(&self, field_id: &str) -> Option<&FieldMeta> {
  56. self.grid_meta.fields.iter().find(|field| field.id == field_id)
  57. }
  58. pub fn get_field_orders(&self) -> Vec<FieldOrder> {
  59. self.grid_meta.fields.iter().map(FieldOrder::from).collect()
  60. }
  61. pub fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> CollaborateResult<Vec<FieldMeta>> {
  62. match field_orders {
  63. None => Ok(self.grid_meta.fields.clone()),
  64. Some(field_orders) => {
  65. let field_by_field_id = self
  66. .grid_meta
  67. .fields
  68. .iter()
  69. .map(|field| (&field.id, field))
  70. .collect::<HashMap<&String, &FieldMeta>>();
  71. let fields = field_orders
  72. .iter()
  73. .flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
  74. None => {
  75. tracing::error!("Can't find the field with id: {}", field_order.field_id);
  76. None
  77. }
  78. Some(field) => Some((*field).clone()),
  79. })
  80. .collect::<Vec<FieldMeta>>();
  81. Ok(fields)
  82. }
  83. }
  84. }
  85. pub fn update_field(&mut self, changeset: FieldChangeset) -> CollaborateResult<Option<GridChangeset>> {
  86. let field_id = changeset.field_id.clone();
  87. self.modify_field(&field_id, |field| {
  88. let mut is_changed = None;
  89. if let Some(name) = changeset.name {
  90. field.name = name;
  91. is_changed = Some(())
  92. }
  93. if let Some(desc) = changeset.desc {
  94. field.desc = desc;
  95. is_changed = Some(())
  96. }
  97. if let Some(field_type) = changeset.field_type {
  98. field.field_type = field_type;
  99. is_changed = Some(())
  100. }
  101. if let Some(frozen) = changeset.frozen {
  102. field.frozen = frozen;
  103. is_changed = Some(())
  104. }
  105. if let Some(visibility) = changeset.visibility {
  106. field.visibility = visibility;
  107. is_changed = Some(())
  108. }
  109. if let Some(width) = changeset.width {
  110. field.width = width;
  111. is_changed = Some(())
  112. }
  113. if let Some(type_options) = changeset.type_options {
  114. field.type_options = type_options;
  115. is_changed = Some(())
  116. }
  117. Ok(is_changed)
  118. })
  119. }
  120. pub fn create_block(&mut self, block: GridBlockMeta) -> CollaborateResult<Option<GridChangeset>> {
  121. self.modify_grid(|grid| {
  122. if grid.blocks.iter().any(|b| b.block_id == block.block_id) {
  123. tracing::warn!("Duplicate grid block");
  124. Ok(None)
  125. } else {
  126. match grid.blocks.last() {
  127. None => grid.blocks.push(block),
  128. Some(last_block) => {
  129. if last_block.start_row_index > block.start_row_index
  130. && last_block.len() > block.start_row_index
  131. {
  132. let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string();
  133. return Err(CollaborateError::internal().context(msg))
  134. }
  135. grid.blocks.push(block);
  136. }
  137. }
  138. Ok(Some(()))
  139. }
  140. })
  141. }
  142. pub fn get_blocks(&self) -> Vec<GridBlockMeta> {
  143. self.grid_meta.blocks.clone()
  144. }
  145. pub fn update_block(&mut self, changeset: GridBlockMetaChangeset) -> CollaborateResult<Option<GridChangeset>> {
  146. let block_id = changeset.block_id.clone();
  147. self.modify_block(&block_id, |block| {
  148. let mut is_changed = None;
  149. if let Some(row_count) = changeset.row_count {
  150. block.row_count = row_count;
  151. is_changed = Some(());
  152. }
  153. if let Some(start_row_index) = changeset.start_row_index {
  154. block.start_row_index = start_row_index;
  155. is_changed = Some(());
  156. }
  157. Ok(is_changed)
  158. })
  159. }
  160. pub fn md5(&self) -> String {
  161. md5(&self.delta.to_delta_bytes())
  162. }
  163. pub fn delta_str(&self) -> String {
  164. self.delta.to_delta_str()
  165. }
  166. pub fn delta_bytes(&self) -> Bytes {
  167. self.delta.to_delta_bytes()
  168. }
  169. pub fn fields(&self) -> &[FieldMeta] {
  170. &self.grid_meta.fields
  171. }
  172. fn modify_grid<F>(&mut self, f: F) -> CollaborateResult<Option<GridChangeset>>
  173. where
  174. F: FnOnce(&mut GridMeta) -> CollaborateResult<Option<()>>,
  175. {
  176. let cloned_grid = self.grid_meta.clone();
  177. match f(Arc::make_mut(&mut self.grid_meta))? {
  178. None => Ok(None),
  179. Some(_) => {
  180. let old = json_from_grid(&cloned_grid)?;
  181. let new = json_from_grid(&self.grid_meta)?;
  182. match cal_diff::<PlainTextAttributes>(old, new) {
  183. None => Ok(None),
  184. Some(delta) => {
  185. self.delta = self.delta.compose(&delta)?;
  186. Ok(Some(GridChangeset { delta, md5: self.md5() }))
  187. }
  188. }
  189. }
  190. }
  191. }
  192. pub fn modify_block<F>(&mut self, block_id: &str, f: F) -> CollaborateResult<Option<GridChangeset>>
  193. where
  194. F: FnOnce(&mut GridBlockMeta) -> CollaborateResult<Option<()>>,
  195. {
  196. self.modify_grid(
  197. |grid| match grid.blocks.iter().position(|block| block.block_id == block_id) {
  198. None => {
  199. tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id);
  200. Ok(None)
  201. }
  202. Some(index) => f(&mut grid.blocks[index]),
  203. },
  204. )
  205. }
  206. pub fn modify_field<F>(&mut self, field_id: &str, f: F) -> CollaborateResult<Option<GridChangeset>>
  207. where
  208. F: FnOnce(&mut FieldMeta) -> CollaborateResult<Option<()>>,
  209. {
  210. self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) {
  211. None => {
  212. tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id);
  213. Ok(None)
  214. }
  215. Some(index) => f(&mut grid.fields[index]),
  216. })
  217. }
  218. }
  219. fn json_from_grid(grid: &Arc<GridMeta>) -> CollaborateResult<String> {
  220. let json = serde_json::to_string(grid)
  221. .map_err(|err| internal_error(format!("Serialize grid to json str failed. {:?}", err)))?;
  222. Ok(json)
  223. }
  224. pub struct GridChangeset {
  225. pub delta: GridMetaDelta,
  226. /// md5: the md5 of the grid after applying the change.
  227. pub md5: String,
  228. }
  229. pub fn make_grid_delta(grid_meta: &GridMeta) -> GridMetaDelta {
  230. let json = serde_json::to_string(&grid_meta).unwrap();
  231. PlainTextDeltaBuilder::new().insert(&json).build()
  232. }
  233. pub fn make_grid_revisions(user_id: &str, grid_meta: &GridMeta) -> RepeatedRevision {
  234. let delta = make_grid_delta(grid_meta);
  235. let bytes = delta.to_delta_bytes();
  236. let revision = Revision::initial_revision(user_id, &grid_meta.grid_id, bytes);
  237. revision.into()
  238. }
  239. impl std::default::Default for GridMetaPad {
  240. fn default() -> Self {
  241. let grid = GridMeta {
  242. grid_id: uuid(),
  243. fields: vec![],
  244. blocks: vec![],
  245. };
  246. let delta = make_grid_delta(&grid);
  247. GridMetaPad {
  248. grid_meta: Arc::new(grid),
  249. delta,
  250. }
  251. }
  252. }