RangesManager.coffee 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. RangesTracker = require "./RangesTracker"
  2. logger = require "logger-sharelatex"
  3. _ = require "lodash"
  4. module.exports = RangesManager =
  5. MAX_COMMENTS: 500
  6. MAX_CHANGES: 2000
  7. applyUpdate: (project_id, doc_id, entries = {}, updates = [], newDocLines, callback = (error, new_entries, ranges_were_collapsed) ->) ->
  8. {changes, comments} = _.cloneDeep(entries)
  9. rangesTracker = new RangesTracker(changes, comments)
  10. emptyRangeCountBefore = RangesManager._emptyRangesCount(rangesTracker)
  11. for update in updates
  12. rangesTracker.track_changes = !!update.meta.tc
  13. if !!update.meta.tc
  14. rangesTracker.setIdSeed(update.meta.tc)
  15. for op in update.op
  16. try
  17. rangesTracker.applyOp(op, { user_id: update.meta?.user_id })
  18. catch error
  19. return callback(error)
  20. if rangesTracker.changes?.length > RangesManager.MAX_CHANGES or rangesTracker.comments?.length > RangesManager.MAX_COMMENTS
  21. return callback new Error("too many comments or tracked changes")
  22. try
  23. # This is a consistency check that all of our ranges and
  24. # comments still match the corresponding text
  25. rangesTracker.validate(newDocLines.join("\n"))
  26. catch error
  27. logger.error {err: error, project_id, doc_id, newDocLines, updates}, "error validating ranges"
  28. return callback(error)
  29. emptyRangeCountAfter = RangesManager._emptyRangesCount(rangesTracker)
  30. rangesWereCollapsed = emptyRangeCountAfter > emptyRangeCountBefore
  31. response = RangesManager._getRanges rangesTracker
  32. logger.log {project_id, doc_id, changesCount: response.changes?.length, commentsCount: response.comments?.length, rangesWereCollapsed}, "applied updates to ranges"
  33. callback null, response, rangesWereCollapsed
  34. acceptChanges: (change_ids, ranges, callback = (error, ranges) ->) ->
  35. {changes, comments} = ranges
  36. logger.log "accepting #{ change_ids.length } changes in ranges"
  37. rangesTracker = new RangesTracker(changes, comments)
  38. rangesTracker.removeChangeIds(change_ids)
  39. response = RangesManager._getRanges(rangesTracker)
  40. callback null, response
  41. deleteComment: (comment_id, ranges, callback = (error, ranges) ->) ->
  42. {changes, comments} = ranges
  43. logger.log {comment_id}, "deleting comment in ranges"
  44. rangesTracker = new RangesTracker(changes, comments)
  45. rangesTracker.removeCommentId(comment_id)
  46. response = RangesManager._getRanges(rangesTracker)
  47. callback null, response
  48. _getRanges: (rangesTracker) ->
  49. # Return the minimal data structure needed, since most documents won't have any
  50. # changes or comments
  51. response = {}
  52. if rangesTracker.changes?.length > 0
  53. response ?= {}
  54. response.changes = rangesTracker.changes
  55. if rangesTracker.comments?.length > 0
  56. response ?= {}
  57. response.comments = rangesTracker.comments
  58. return response
  59. _emptyRangesCount: (ranges) ->
  60. count = 0
  61. for comment in (ranges.comments or [])
  62. if comment.op.c == ""
  63. count++
  64. for change in (ranges.changes or []) when change.op.i?
  65. if change.op.i == ""
  66. count++
  67. return count