grid_meta_pad.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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. gen_field_id, gen_grid_id, FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockMeta,
  7. GridBlockMetaChangeset, GridMeta,
  8. };
  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. pub trait JsonDeserializer {
  19. fn deserialize(&self, type_option_data: Vec<u8>) -> CollaborateResult<String>;
  20. }
  21. impl GridMetaPad {
  22. pub fn from_delta(delta: GridMetaDelta) -> CollaborateResult<Self> {
  23. let s = delta.to_str()?;
  24. let grid: GridMeta = serde_json::from_str(&s)
  25. .map_err(|e| CollaborateError::internal().context(format!("Deserialize delta to grid failed: {}", e)))?;
  26. Ok(Self {
  27. grid_meta: Arc::new(grid),
  28. delta,
  29. })
  30. }
  31. pub fn from_revisions(_grid_id: &str, revisions: Vec<Revision>) -> CollaborateResult<Self> {
  32. let grid_delta: GridMetaDelta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
  33. Self::from_delta(grid_delta)
  34. }
  35. #[tracing::instrument(level = "debug", skip_all, err)]
  36. pub fn create_field(
  37. &mut self,
  38. new_field_meta: FieldMeta,
  39. start_field_id: Option<String>,
  40. ) -> CollaborateResult<Option<GridChangeset>> {
  41. self.modify_grid(|grid_meta| {
  42. // Check if the field exists or not
  43. if grid_meta
  44. .fields
  45. .iter()
  46. .any(|field_meta| field_meta.id == new_field_meta.id)
  47. {
  48. tracing::error!("Duplicate grid field");
  49. return Ok(None);
  50. }
  51. let insert_index = match start_field_id {
  52. None => None,
  53. Some(start_field_id) => grid_meta.fields.iter().position(|field| field.id == start_field_id),
  54. };
  55. match insert_index {
  56. None => grid_meta.fields.push(new_field_meta),
  57. Some(index) => grid_meta.fields.insert(index, new_field_meta),
  58. }
  59. Ok(Some(()))
  60. })
  61. }
  62. pub fn delete_field(&mut self, field_id: &str) -> CollaborateResult<Option<GridChangeset>> {
  63. self.modify_grid(
  64. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
  65. None => Ok(None),
  66. Some(index) => {
  67. grid_meta.fields.remove(index);
  68. Ok(Some(()))
  69. }
  70. },
  71. )
  72. }
  73. pub fn duplicate_field(&mut self, field_id: &str) -> CollaborateResult<Option<GridChangeset>> {
  74. self.modify_grid(
  75. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
  76. None => Ok(None),
  77. Some(index) => {
  78. let mut duplicate_field_meta = grid_meta.fields[index].clone();
  79. duplicate_field_meta.id = gen_field_id();
  80. duplicate_field_meta.name = format!("{} (copy)", duplicate_field_meta.name);
  81. grid_meta.fields.insert(index + 1, duplicate_field_meta);
  82. Ok(Some(()))
  83. }
  84. },
  85. )
  86. }
  87. pub fn switch_to_field<B>(
  88. &mut self,
  89. field_id: &str,
  90. field_type: FieldType,
  91. type_option_json_builder: B,
  92. ) -> CollaborateResult<Option<GridChangeset>>
  93. where
  94. B: FnOnce(&FieldType) -> String,
  95. {
  96. self.modify_grid(|grid_meta| {
  97. //
  98. match grid_meta.fields.iter_mut().find(|field_meta| field_meta.id == field_id) {
  99. None => {
  100. tracing::warn!("Can not find the field with id: {}", field_id);
  101. Ok(None)
  102. }
  103. Some(field_meta) => {
  104. if field_meta.get_type_option_str(Some(field_type.clone())).is_none() {
  105. let type_option_json = type_option_json_builder(&field_type);
  106. field_meta.insert_type_option_str(&field_type, type_option_json);
  107. }
  108. field_meta.field_type = field_type;
  109. Ok(Some(()))
  110. }
  111. }
  112. })
  113. }
  114. pub fn update_field<T: JsonDeserializer>(
  115. &mut self,
  116. changeset: FieldChangesetParams,
  117. deserializer: T,
  118. ) -> CollaborateResult<Option<GridChangeset>> {
  119. let field_id = changeset.field_id.clone();
  120. self.modify_field(&field_id, |field| {
  121. let mut is_changed = None;
  122. if let Some(name) = changeset.name {
  123. field.name = name;
  124. is_changed = Some(())
  125. }
  126. if let Some(desc) = changeset.desc {
  127. field.desc = desc;
  128. is_changed = Some(())
  129. }
  130. if let Some(field_type) = changeset.field_type {
  131. field.field_type = field_type;
  132. is_changed = Some(())
  133. }
  134. if let Some(frozen) = changeset.frozen {
  135. field.frozen = frozen;
  136. is_changed = Some(())
  137. }
  138. if let Some(visibility) = changeset.visibility {
  139. field.visibility = visibility;
  140. is_changed = Some(())
  141. }
  142. if let Some(width) = changeset.width {
  143. field.width = width;
  144. is_changed = Some(())
  145. }
  146. if let Some(type_option_data) = changeset.type_option_data {
  147. match deserializer.deserialize(type_option_data) {
  148. Ok(json_str) => {
  149. let field_type = field.field_type.clone();
  150. field.insert_type_option_str(&field_type, json_str);
  151. is_changed = Some(())
  152. }
  153. Err(err) => {
  154. tracing::error!("Deserialize data to type option json failed: {}", err);
  155. }
  156. }
  157. }
  158. Ok(is_changed)
  159. })
  160. }
  161. pub fn get_field(&self, field_id: &str) -> Option<&FieldMeta> {
  162. self.grid_meta.fields.iter().find(|field| field.id == field_id)
  163. }
  164. pub fn replace_field(&mut self, field_meta: FieldMeta) -> CollaborateResult<Option<GridChangeset>> {
  165. self.modify_grid(
  166. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_meta.id) {
  167. None => Ok(None),
  168. Some(index) => {
  169. grid_meta.fields.remove(index);
  170. grid_meta.fields.insert(index, field_meta);
  171. Ok(Some(()))
  172. }
  173. },
  174. )
  175. }
  176. pub fn contain_field(&self, field_id: &str) -> bool {
  177. self.grid_meta.fields.iter().any(|field| field.id == field_id)
  178. }
  179. pub fn get_field_orders(&self) -> Vec<FieldOrder> {
  180. self.grid_meta.fields.iter().map(FieldOrder::from).collect()
  181. }
  182. pub fn get_field_metas(&self, field_orders: Option<Vec<FieldOrder>>) -> CollaborateResult<Vec<FieldMeta>> {
  183. match field_orders {
  184. None => Ok(self.grid_meta.fields.clone()),
  185. Some(field_orders) => {
  186. let field_by_field_id = self
  187. .grid_meta
  188. .fields
  189. .iter()
  190. .map(|field| (&field.id, field))
  191. .collect::<HashMap<&String, &FieldMeta>>();
  192. let fields = field_orders
  193. .iter()
  194. .flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
  195. None => {
  196. tracing::error!("Can't find the field with id: {}", field_order.field_id);
  197. None
  198. }
  199. Some(field) => Some((*field).clone()),
  200. })
  201. .collect::<Vec<FieldMeta>>();
  202. Ok(fields)
  203. }
  204. }
  205. }
  206. pub fn create_block_meta(&mut self, block: GridBlockMeta) -> CollaborateResult<Option<GridChangeset>> {
  207. self.modify_grid(|grid_meta| {
  208. if grid_meta.blocks.iter().any(|b| b.block_id == block.block_id) {
  209. tracing::warn!("Duplicate grid block");
  210. Ok(None)
  211. } else {
  212. match grid_meta.blocks.last() {
  213. None => grid_meta.blocks.push(block),
  214. Some(last_block) => {
  215. if last_block.start_row_index > block.start_row_index
  216. && last_block.len() > block.start_row_index
  217. {
  218. let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string();
  219. return Err(CollaborateError::internal().context(msg))
  220. }
  221. grid_meta.blocks.push(block);
  222. }
  223. }
  224. Ok(Some(()))
  225. }
  226. })
  227. }
  228. pub fn get_block_metas(&self) -> Vec<GridBlockMeta> {
  229. self.grid_meta.blocks.clone()
  230. }
  231. pub fn update_block_meta(&mut self, changeset: GridBlockMetaChangeset) -> CollaborateResult<Option<GridChangeset>> {
  232. let block_id = changeset.block_id.clone();
  233. self.modify_block(&block_id, |block| {
  234. let mut is_changed = None;
  235. if let Some(row_count) = changeset.row_count {
  236. block.row_count = row_count;
  237. is_changed = Some(());
  238. }
  239. if let Some(start_row_index) = changeset.start_row_index {
  240. block.start_row_index = start_row_index;
  241. is_changed = Some(());
  242. }
  243. Ok(is_changed)
  244. })
  245. }
  246. pub fn md5(&self) -> String {
  247. md5(&self.delta.to_delta_bytes())
  248. }
  249. pub fn delta_str(&self) -> String {
  250. self.delta.to_delta_str()
  251. }
  252. pub fn delta_bytes(&self) -> Bytes {
  253. self.delta.to_delta_bytes()
  254. }
  255. pub fn fields(&self) -> &[FieldMeta] {
  256. &self.grid_meta.fields
  257. }
  258. fn modify_grid<F>(&mut self, f: F) -> CollaborateResult<Option<GridChangeset>>
  259. where
  260. F: FnOnce(&mut GridMeta) -> CollaborateResult<Option<()>>,
  261. {
  262. let cloned_grid = self.grid_meta.clone();
  263. match f(Arc::make_mut(&mut self.grid_meta))? {
  264. None => Ok(None),
  265. Some(_) => {
  266. let old = json_from_grid(&cloned_grid)?;
  267. let new = json_from_grid(&self.grid_meta)?;
  268. match cal_diff::<PlainTextAttributes>(old, new) {
  269. None => Ok(None),
  270. Some(delta) => {
  271. self.delta = self.delta.compose(&delta)?;
  272. Ok(Some(GridChangeset { delta, md5: self.md5() }))
  273. }
  274. }
  275. }
  276. }
  277. }
  278. pub fn modify_block<F>(&mut self, block_id: &str, f: F) -> CollaborateResult<Option<GridChangeset>>
  279. where
  280. F: FnOnce(&mut GridBlockMeta) -> CollaborateResult<Option<()>>,
  281. {
  282. self.modify_grid(
  283. |grid_meta| match grid_meta.blocks.iter().position(|block| block.block_id == block_id) {
  284. None => {
  285. tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id);
  286. Ok(None)
  287. }
  288. Some(index) => f(&mut grid_meta.blocks[index]),
  289. },
  290. )
  291. }
  292. pub fn modify_field<F>(&mut self, field_id: &str, f: F) -> CollaborateResult<Option<GridChangeset>>
  293. where
  294. F: FnOnce(&mut FieldMeta) -> CollaborateResult<Option<()>>,
  295. {
  296. self.modify_grid(
  297. |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
  298. None => {
  299. tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id);
  300. Ok(None)
  301. }
  302. Some(index) => f(&mut grid_meta.fields[index]),
  303. },
  304. )
  305. }
  306. }
  307. fn json_from_grid(grid: &Arc<GridMeta>) -> CollaborateResult<String> {
  308. let json = serde_json::to_string(grid)
  309. .map_err(|err| internal_error(format!("Serialize grid to json str failed. {:?}", err)))?;
  310. Ok(json)
  311. }
  312. pub struct GridChangeset {
  313. pub delta: GridMetaDelta,
  314. /// md5: the md5 of the grid after applying the change.
  315. pub md5: String,
  316. }
  317. pub fn make_grid_delta(grid_meta: &GridMeta) -> GridMetaDelta {
  318. let json = serde_json::to_string(&grid_meta).unwrap();
  319. PlainTextDeltaBuilder::new().insert(&json).build()
  320. }
  321. pub fn make_grid_revisions(user_id: &str, grid_meta: &GridMeta) -> RepeatedRevision {
  322. let delta = make_grid_delta(grid_meta);
  323. let bytes = delta.to_delta_bytes();
  324. let revision = Revision::initial_revision(user_id, &grid_meta.grid_id, bytes);
  325. revision.into()
  326. }
  327. impl std::default::Default for GridMetaPad {
  328. fn default() -> Self {
  329. let grid = GridMeta {
  330. grid_id: gen_grid_id(),
  331. fields: vec![],
  332. blocks: vec![],
  333. };
  334. let delta = make_grid_delta(&grid);
  335. GridMetaPad {
  336. grid_meta: Arc::new(grid),
  337. delta,
  338. }
  339. }
  340. }