overleaf/services/document-updater/app/coffee/RangesManager.coffee

76 lines
2.9 KiB
CoffeeScript
Raw Normal View History

RangesTracker = require "./RangesTracker"
logger = require "logger-sharelatex"
_ = require "lodash"
module.exports = RangesManager =
MAX_COMMENTS: 500
2017-02-24 13:58:42 +00:00
MAX_CHANGES: 2000
applyUpdate: (project_id, doc_id, entries = {}, updates = [], newDocLines, callback = (error, new_entries, ranges_were_collapsed) ->) ->
{changes, comments} = _.cloneDeep(entries)
rangesTracker = new RangesTracker(changes, comments)
emptyRangeCountBefore = RangesManager._emptyRangesCount(rangesTracker)
for update in updates
rangesTracker.track_changes = !!update.meta.tc
if !!update.meta.tc
rangesTracker.setIdSeed(update.meta.tc)
for op in update.op
2017-03-06 19:05:11 +00:00
try
rangesTracker.applyOp(op, { user_id: update.meta?.user_id })
catch error
return callback(error)
if rangesTracker.changes?.length > RangesManager.MAX_CHANGES or rangesTracker.comments?.length > RangesManager.MAX_COMMENTS
return callback new Error("too many comments or tracked changes")
try
# This is a consistency check that all of our ranges and
# comments still match the corresponding text
rangesTracker.validate(newDocLines.join("\n"))
catch error
logger.error {err: error, project_id, doc_id, newDocLines, updates}, "error validating ranges"
return callback(error)
emptyRangeCountAfter = RangesManager._emptyRangesCount(rangesTracker)
rangesWereCollapsed = emptyRangeCountAfter > emptyRangeCountBefore
response = RangesManager._getRanges rangesTracker
logger.log {project_id, doc_id, changesCount: response.changes?.length, commentsCount: response.comments?.length, rangesWereCollapsed}, "applied updates to ranges"
callback null, response, rangesWereCollapsed
2017-05-05 14:12:06 +00:00
acceptChanges: (change_ids, ranges, callback = (error, ranges) ->) ->
2017-05-04 14:32:54 +00:00
{changes, comments} = ranges
2017-05-08 15:34:17 +00:00
logger.log "accepting #{ change_ids.length } changes in ranges"
2017-05-04 14:32:54 +00:00
rangesTracker = new RangesTracker(changes, comments)
2017-05-08 15:08:42 +00:00
rangesTracker.removeChangeIds(change_ids)
2017-05-04 14:32:54 +00:00
response = RangesManager._getRanges(rangesTracker)
callback null, response
2017-01-24 14:57:11 +00:00
deleteComment: (comment_id, ranges, callback = (error, ranges) ->) ->
{changes, comments} = ranges
logger.log {comment_id}, "deleting comment in ranges"
2017-01-24 14:57:11 +00:00
rangesTracker = new RangesTracker(changes, comments)
rangesTracker.removeCommentId(comment_id)
response = RangesManager._getRanges(rangesTracker)
callback null, response
_getRanges: (rangesTracker) ->
# Return the minimal data structure needed, since most documents won't have any
# changes or comments
response = {}
if rangesTracker.changes?.length > 0
response ?= {}
response.changes = rangesTracker.changes
if rangesTracker.comments?.length > 0
response ?= {}
response.comments = rangesTracker.comments
return response
_emptyRangesCount: (ranges) ->
count = 0
for comment in (ranges.comments or [])
if comment.op.c == ""
count++
for change in (ranges.changes or []) when change.op.i?
if change.op.i == ""
count++
return count