4f9a764d750fc65a2b03592d2489c18685725cd60c2c1d38f2b0f7c841d544c24cbc04fb0095b9391a9f59b5cec12588db85f70d2c47a270fd62dbce35acf1 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import {arrayFilter, arrayMap} from '../../helpers/array';
  2. /**
  3. * Clean and extend patches from jsonpatch observer.
  4. *
  5. * @param {Array} patches
  6. * @returns {Array}
  7. */
  8. export function cleanPatches(patches) {
  9. const newOrRemovedColumns = [];
  10. /**
  11. * If observeChanges uses native Object.observe method, then it produces patches for length property. Filter them.
  12. * If path can't be parsed. Filter it.
  13. */
  14. patches = arrayFilter(patches, (patch) => {
  15. if (/[/]length/ig.test(patch.path)) {
  16. return false;
  17. }
  18. if (!parsePath(patch.path)) {
  19. return false;
  20. }
  21. return true;
  22. });
  23. /**
  24. * Extend patches with changed cells coords
  25. */
  26. patches = arrayMap(patches, (patch) => {
  27. const coords = parsePath(patch.path);
  28. patch.row = coords.row;
  29. patch.col = coords.col;
  30. return patch;
  31. });
  32. /**
  33. * Removing or adding column will produce one patch for each table row.
  34. * Leaves only one patch for each column add/remove operation.
  35. */
  36. patches = arrayFilter(patches, (patch) => {
  37. if (['add', 'remove'].indexOf(patch.op) !== -1 && !isNaN(patch.col)) {
  38. if (newOrRemovedColumns.indexOf(patch.col) !== -1) {
  39. return false;
  40. }
  41. newOrRemovedColumns.push(patch.col);
  42. }
  43. return true;
  44. });
  45. newOrRemovedColumns.length = 0;
  46. return patches;
  47. }
  48. /**
  49. * Extract coordinates from path where data was changed.
  50. *
  51. * @param {String} path Path describing where data was changed.
  52. * @returns {Object|null} Returns an object with `row` and `col` properties or `null` if path doesn't have necessary information.
  53. */
  54. export function parsePath(path) {
  55. const match = path.match(/^\/(\d+)\/?(.*)?$/);
  56. if (!match) {
  57. return null;
  58. }
  59. const [, row, column] = match;
  60. return {
  61. row: parseInt(row, 10),
  62. col: /^\d*$/.test(column) ? parseInt(column, 10) : column
  63. };
  64. }