grid_meta_pad.rs 10 KB

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