From c96f607e9a9f2e47341738b7d24549a3a842e3f9 Mon Sep 17 00:00:00 2001
From: barlas <yannisbarlas@gmail.com>
Date: Fri, 6 Jan 2017 17:16:45 +0200
Subject: [PATCH] more robust handling for tracked additions

---
 .../track_change/TrackChangeHTMLConverter.js  |  4 +-
 .../track_change/TrackChangesProvider.js      | 99 ++++++++-----------
 2 files changed, 43 insertions(+), 60 deletions(-)

diff --git a/app/components/SimpleEditor/elements/track_change/TrackChangeHTMLConverter.js b/app/components/SimpleEditor/elements/track_change/TrackChangeHTMLConverter.js
index 8a598e9..40e61df 100644
--- a/app/components/SimpleEditor/elements/track_change/TrackChangeHTMLConverter.js
+++ b/app/components/SimpleEditor/elements/track_change/TrackChangeHTMLConverter.js
@@ -5,7 +5,7 @@ export default {
   import: function (element, node, converter) {
     node.status = element.attr('status')
     node.user = {
-      // roles: element.attr('roles').split(','),
+      roles: element.attr('roles').split(','),
       user: element.attr('username')
     }
   },
@@ -15,7 +15,7 @@ export default {
 
     element.setAttribute('status', status)
 
-    element.setAttribute('role', user.roles.join(','))
+    element.setAttribute('roles', user.roles.join(','))
     element.setAttribute('username', user.username)
   }
 }
diff --git a/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js b/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js
index ff8ced4..2666404 100644
--- a/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js
+++ b/app/components/SimpleEditor/elements/track_change/TrackChangesProvider.js
@@ -55,6 +55,7 @@ class TrackChangesProvider {
     if (notOnTrack) return this.insertCharacterWithAddAnnotation(options)
 
     if (isOnAdd) {
+      // annotation gets expanded automatically, unless the selection is on its left edge
       const annotation = this.getAnnotationByStatus('add')
       const isOnLeftEdge = this.isOnLeftEdge(annotation)
 
@@ -70,6 +71,9 @@ class TrackChangesProvider {
       const isOnRightEdge = this.isOnRightEdge(annotation)
       const withinAnnotation = this.isSelectionContainedWithin(annotation, true)
 
+      // if contained within the delete annotation, move it to the edge,
+      // insert character, set event to null so that the character does
+      // not get inserted twice, and handle again
       if (withinAnnotation) {
         this.moveCursorTo(annotation.endOffset)
         this.insertCharacterWithoutExpandingAnnotation(annotation, options)
@@ -87,66 +91,45 @@ class TrackChangesProvider {
   }
 
   handleAddNonCollapsed (options) {
-    // const { event } = options
     let { selection } = options
 
     const notOnTrack = this.isNotOnTrackAnnotation()
     // const isOnAdd = this.isOnAnnotation('add')
-    // const isOnDelete = this.isOnAnnotation('delete')
+    const isOnDelete = this.isOnAnnotation('delete')
 
     if (notOnTrack) return this.deleteSelectedAndCreateAddition(options)
 
+    // delete all additions of the same user and shorten selection by the
+    // number of deleted characters
     const shortenBy = this.deleteAllOwnAdditions(selection)
-    options.selection = this.updateSelection(selection, selection.startOffset, selection.endOffset - shortenBy)
-    this.deleteSelectedAndCreateAddition(options)
+    const startOffset = selection.startOffset
+    const endOffset = selection.endOffset - shortenBy
+    selection = this.updateSelection(selection, startOffset, endOffset)
+    options.selection = selection
 
-    // if (isOnAdd) {
-    //   const annotation = this.getAnnotationByStatus('add')
-    //   const withinAnnotation = this.isSelectionContainedWithin(annotation)
-    //
-    //   if (withinAnnotation) return this.insertText(event)
-    //
-    //   selection = this.getSelection()
-    //   this.createDeleteAnnotation(selection)
-    //   const allAdditions = this.getAllAnnotationsByStatus('add')
-    //   const firstAddition = minBy(allAdditions, 'startOffset')
-    //   this.deleteAllOwnAdditions()
-    //
-    //   const moveTo = max([firstAddition.startOffset, selection.startOffset])
-    //   this.moveCursorTo(moveTo)
-    //   this.insertText(event)
-    //   selection = this.setSelectionPlusOne('left')
-    //   this.createAddAnnotation(selection)
-    //   this.moveCursorTo('end')
-    //   return
-    // }
-    //
-    // if (isOnDelete) {
-    //   const annotation = this.getAnnotationByStatus('delete')
-    //   const withinAnnotation = this.isSelectionContainedWithin(annotation)
-    //
-    //   if (withinAnnotation) {
-    //     this.moveCursorTo(annotation.endOffset)
-    //     // options.selection =
-    //     this.insertText(event)
-    //     selection = this.setSelectionPlusOne('left')
-    //     this.createAddAnnotation(selection)
-    //     this.separateAnnotations()
-    //     this.moveCursorTo('end')
-    //     return
-    //   }
-    //
-    //   selection = this.getSelection()
-    //   this.expandTrackAnnotation(selection, annotation)
-    //
-    //   this.moveCursorTo(annotation.endOffset)
-    //   this.insertText(event)
-    //   selection = this.setSelectionPlusOne('left')
-    //   this.createAddAnnotation(selection)
-    //   this.separateAnnotations()
-    //   this.moveCursorTo('end')
-    //   return
-    // }
+    if (isOnDelete) {
+      const annotation = this.getAnnotationByStatus('delete')
+      const withinAnnotation = this.isSelectionContainedWithin(annotation)
+
+      if (withinAnnotation) {
+        // if selection is wholly contained within a delete annotation,
+        // move to the end of the annotation and handle again
+        this.moveCursorTo(annotation.endOffset)
+        options.selection = this.getSelection()
+        return this.handleAddCollapsed(options)
+      }
+    }
+
+    // after deleting all own additions, there is still text selected
+    // mark it as deleted and add new addition annotation at the end
+    if (selection.endOffset > selection.startOffset) {
+      return this.deleteSelectedAndCreateAddition(options)
+    }
+
+    // if you got here, deleting all own additions left a collapsed selection
+    // (ie. the whole selection was on an own addition annotation)
+    // since selection is collapsed, handle it as such
+    return this.handleAddCollapsed(options)
   }
 
   deleteSelectedAndCreateAddition (options) {
@@ -155,17 +138,14 @@ class TrackChangesProvider {
     this.createDeleteAnnotation(selection)
     this.moveCursorTo('end', selection)
 
-    const deleteAnnotation = this.getAnnotationByStatus('delete')
-    this.insertCharacterWithoutExpandingAnnotation(deleteAnnotation, options)
-    this.createAdditionAnnotationOnLastChar()
+    // selection is now collapsed, so handle it as collapsed
+    this.handleAddCollapsed(options)
   }
 
-  // Inserts a character and then marks it as an add annotation
-  // If an add annotation existed on the left side of the new character already
-  // substance will expand this annotation on insertion
   insertCharacterWithAddAnnotation (options) {
     const { event } = options
     this.insertText(event)
+
     // TODO -- watch it with additions by other users
     this.createAdditionAnnotationOnLastChar()
   }
@@ -382,7 +362,10 @@ class TrackChangesProvider {
         node: {
           status: status,
           type: 'track-change',
-          user: user
+          user: {
+            roles: user.roles,
+            username: user.username
+          }
         }
       }
       createAnnotation(tx, newNode)
-- 
GitLab