grid_meta_pad.rs 15 KB

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