mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Show nice diffs using ace and markers
This commit is contained in:
parent
bf21305c68
commit
1a91036bb6
7 changed files with 201 additions and 10 deletions
|
@ -1,5 +1,4 @@
|
||||||
define [
|
define [
|
||||||
"history/util"
|
|
||||||
"libs/mustache"
|
"libs/mustache"
|
||||||
"libs/backbone"
|
"libs/backbone"
|
||||||
], (util)->
|
], (util)->
|
||||||
|
@ -9,7 +8,7 @@ define [
|
||||||
events:
|
events:
|
||||||
"scroll" : "loadUntilFull"
|
"scroll" : "loadUntilFull"
|
||||||
|
|
||||||
initialize: ->
|
initialize: () ->
|
||||||
@itemViews = []
|
@itemViews = []
|
||||||
@atEndOfCollection = false
|
@atEndOfCollection = false
|
||||||
|
|
||||||
|
@ -34,6 +33,8 @@ define [
|
||||||
index = @collection.indexOf(model)
|
index = @collection.indexOf(model)
|
||||||
elementAtIndex = @$(".change-list").children()[index]
|
elementAtIndex = @$(".change-list").children()[index]
|
||||||
view.$el.insertBefore(elementAtIndex)
|
view.$el.insertBefore(elementAtIndex)
|
||||||
|
view.on "click", (e, v) =>
|
||||||
|
@trigger "change_diff", v.model.get("version")
|
||||||
|
|
||||||
listShorterThanContainer: ->
|
listShorterThanContainer: ->
|
||||||
@$el.height() > @$(".change-list").height()
|
@$el.height() > @$(".change-list").height()
|
||||||
|
@ -81,6 +82,9 @@ define [
|
||||||
|
|
||||||
ChangeListItemView = Backbone.View.extend
|
ChangeListItemView = Backbone.View.extend
|
||||||
tagName: "li"
|
tagName: "li"
|
||||||
|
|
||||||
|
events:
|
||||||
|
"click a": "onClick"
|
||||||
|
|
||||||
template : $("#changeListItemTemplate").html()
|
template : $("#changeListItemTemplate").html()
|
||||||
|
|
||||||
|
@ -97,5 +101,9 @@ define [
|
||||||
# modelView.end_ts = util.formatDate(modelView.end_ts)
|
# modelView.end_ts = util.formatDate(modelView.end_ts)
|
||||||
return modelView
|
return modelView
|
||||||
|
|
||||||
|
onClick: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
@trigger "click", e, @
|
||||||
|
|
||||||
return ChangeListView
|
return ChangeListView
|
||||||
|
|
||||||
|
|
139
services/web/public/coffee/track-changes/DiffView.coffee
Normal file
139
services/web/public/coffee/track-changes/DiffView.coffee
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
define [
|
||||||
|
"ace/ace"
|
||||||
|
"ace/mode/latex"
|
||||||
|
"ace/range"
|
||||||
|
"libs/backbone"
|
||||||
|
], (Ace, LatexMode, Range)->
|
||||||
|
DiffView = Backbone.View.extend
|
||||||
|
initialize: () ->
|
||||||
|
@model.on "change:diff", () => @render()
|
||||||
|
@render()
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
diff = @model.get("diff")
|
||||||
|
return unless diff?
|
||||||
|
@createAceEditor()
|
||||||
|
@aceEditor.setValue(@getPlainDiffContent())
|
||||||
|
@aceEditor.clearSelection()
|
||||||
|
session = @aceEditor.getSession()
|
||||||
|
session.setMode(new LatexMode.Mode())
|
||||||
|
session.setUseWrapMode(true)
|
||||||
|
@insertMarkers()
|
||||||
|
return @
|
||||||
|
|
||||||
|
createAceEditor: () ->
|
||||||
|
@$el.empty()
|
||||||
|
$editor = $("<div/>")
|
||||||
|
@$el.append($editor)
|
||||||
|
@aceEditor = Ace.edit($editor[0])
|
||||||
|
@aceEditor.setTheme("ace/theme/#{window.userSettings.theme}")
|
||||||
|
@aceEditor.setReadOnly true
|
||||||
|
@aceEditor.setShowPrintMargin(false)
|
||||||
|
|
||||||
|
@aceEditor.on "mousemove", (e) =>
|
||||||
|
position = @aceEditor.renderer.screenToTextCoordinates(e.clientX, e.clientY)
|
||||||
|
e.position = position
|
||||||
|
@updateVisibleNames(e)
|
||||||
|
|
||||||
|
getPlainDiffContent: () ->
|
||||||
|
content = ""
|
||||||
|
for entry in @model.get("diff") or []
|
||||||
|
content += entry.u or entry.i or entry.d or ""
|
||||||
|
return content
|
||||||
|
|
||||||
|
insertMarkers: () ->
|
||||||
|
row = 0
|
||||||
|
column = 0
|
||||||
|
for entry, i in @model.get("diff") or []
|
||||||
|
content = entry.u or entry.i or entry.d
|
||||||
|
lines = content.split("\n")
|
||||||
|
startRow = row
|
||||||
|
startColumn = column
|
||||||
|
if lines.length > 1
|
||||||
|
endRow = startRow + lines.length - 1
|
||||||
|
endColumn = lines[lines.length - 1].length
|
||||||
|
else
|
||||||
|
endRow = startRow
|
||||||
|
endColumn = startColumn + lines[0].length
|
||||||
|
row = endRow
|
||||||
|
column = endColumn
|
||||||
|
|
||||||
|
range = new Range.Range(
|
||||||
|
startRow, startColumn, endRow, endColumn
|
||||||
|
)
|
||||||
|
@addMarker(range, "change-marker-#{i}", entry)
|
||||||
|
|
||||||
|
addMarker: (range, id, entry) ->
|
||||||
|
session = @aceEditor.getSession()
|
||||||
|
markerBackLayer = @aceEditor.renderer.$markerBack
|
||||||
|
markerFrontLayer = @aceEditor.renderer.$markerFront
|
||||||
|
lineHeight = @aceEditor.renderer.lineHeight
|
||||||
|
if entry.i? or entry.d?
|
||||||
|
hue = 200
|
||||||
|
if entry.i?
|
||||||
|
@_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, """
|
||||||
|
background-color : hsl(#{hue}, 70%, 85%);
|
||||||
|
"""
|
||||||
|
tag = "Added by #{entry.meta.user_id}"
|
||||||
|
if entry.d?
|
||||||
|
@_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, """
|
||||||
|
background-color : hsl(#{hue}, 70%, 95%);
|
||||||
|
"""
|
||||||
|
@_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-foreground", true, """
|
||||||
|
height: #{Math.round(lineHeight/2) - 1}px;
|
||||||
|
border-bottom: 2px solid hsl(#{hue}, 70%, 40%);
|
||||||
|
"""
|
||||||
|
tag = "Deleted by #{entry.meta.user_id}"
|
||||||
|
|
||||||
|
tag += " on #{entry.meta.end_ts}"
|
||||||
|
@_addNameTag session, id, range, tag, """
|
||||||
|
background-color : hsl(#{hue}, 70%, 85%);
|
||||||
|
"""
|
||||||
|
|
||||||
|
_addMarkerWithCustomStyle: (session, markerLayer, range, klass, foreground, style) ->
|
||||||
|
session.addMarker range, klass, (html, range, left, top, config) ->
|
||||||
|
if range.isMultiLine()
|
||||||
|
markerLayer.drawTextMarker(html, range, klass, config, style)
|
||||||
|
else
|
||||||
|
markerLayer.drawSingleLineMarker(html, range, "#{klass} ace_start", config, 0, style)
|
||||||
|
, foreground
|
||||||
|
|
||||||
|
_addNameTag: (session, id, range, content, style) ->
|
||||||
|
@nameMarkers ||= []
|
||||||
|
@nameMarkers.push
|
||||||
|
range: range
|
||||||
|
id: id
|
||||||
|
startRange = new Range.Range(
|
||||||
|
range.start.row, range.start.column
|
||||||
|
range.start.row, session.getScreenLastRowColumn(range.start.row)
|
||||||
|
)
|
||||||
|
session.addMarker startRange, "change-name-marker", (html, range, left, top, config) ->
|
||||||
|
html.push """
|
||||||
|
<div
|
||||||
|
id = '#{id}'
|
||||||
|
class = 'change-name-marker'
|
||||||
|
style = '
|
||||||
|
height: #{config.lineHeight}px;
|
||||||
|
top: #{top}px;
|
||||||
|
left: #{left}px;
|
||||||
|
'
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="name" style="
|
||||||
|
display: none;
|
||||||
|
bottom: #{config.lineHeight + 2}px;
|
||||||
|
#{style}
|
||||||
|
">#{content}</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
, true
|
||||||
|
|
||||||
|
updateVisibleNames: (e) ->
|
||||||
|
for marker in @nameMarkers or []
|
||||||
|
if marker.range.contains(e.position.row, e.position.column)
|
||||||
|
$("##{marker.id}").find(".name").show()
|
||||||
|
else
|
||||||
|
$("##{marker.id}").find(".name").hide()
|
||||||
|
|
||||||
|
return DiffView
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
define [
|
define [
|
||||||
"track-changes/models/ChangeList"
|
"track-changes/models/ChangeList"
|
||||||
|
"track-changes/models/Diff"
|
||||||
"track-changes/ChangeListView"
|
"track-changes/ChangeListView"
|
||||||
], (ChangeList, ChangeListView) ->
|
"track-changes/DiffView"
|
||||||
|
], (ChangeList, Diff, ChangeListView, DiffView) ->
|
||||||
class TrackChangesManager
|
class TrackChangesManager
|
||||||
template: $("#trackChangesPanelTemplate").html()
|
template: $("#trackChangesPanelTemplate").html()
|
||||||
|
|
||||||
|
@ -11,9 +13,9 @@ define [
|
||||||
@hideEl()
|
@hideEl()
|
||||||
|
|
||||||
show: () ->
|
show: () ->
|
||||||
project_id = window.userSettings.project_id
|
@project_id = window.userSettings.project_id
|
||||||
doc_id = @ide.editor.current_doc_id
|
@doc_id = @ide.editor.current_doc_id
|
||||||
@changes = new ChangeList([], doc_id: doc_id, project_id: project_id)
|
@changes = new ChangeList([], doc_id: @doc_id, project_id: @project_id)
|
||||||
|
|
||||||
@changeListView = new ChangeListView(
|
@changeListView = new ChangeListView(
|
||||||
collection : @changes,
|
collection : @changes,
|
||||||
|
@ -22,6 +24,19 @@ define [
|
||||||
@changeListView.render()
|
@changeListView.render()
|
||||||
@changeListView.loadUntilFull()
|
@changeListView.loadUntilFull()
|
||||||
|
|
||||||
|
@changeListView.on "change_diff", (version) =>
|
||||||
|
@diff = new Diff({
|
||||||
|
project_id: @project_id
|
||||||
|
doc_id: @doc_id
|
||||||
|
from: version
|
||||||
|
to: version
|
||||||
|
})
|
||||||
|
@diffView = new DiffView(
|
||||||
|
model: @diff
|
||||||
|
el: @$el.find(".track-changes-diff")
|
||||||
|
)
|
||||||
|
@diff.fetch()
|
||||||
|
|
||||||
@showEl()
|
@showEl()
|
||||||
|
|
||||||
showEl: ->
|
showEl: ->
|
||||||
|
|
|
@ -7,4 +7,5 @@ define [
|
||||||
start_ts: change.meta.start_ts
|
start_ts: change.meta.start_ts
|
||||||
end_ts: change.meta.end_ts
|
end_ts: change.meta.end_ts
|
||||||
user_id: change.meta.user_id
|
user_id: change.meta.user_id
|
||||||
|
version: change.v
|
||||||
}
|
}
|
|
@ -7,13 +7,12 @@ define [
|
||||||
batchSize: 3
|
batchSize: 3
|
||||||
|
|
||||||
initialize: (models, @options) ->
|
initialize: (models, @options) ->
|
||||||
console.log arguments
|
|
||||||
|
|
||||||
url: () ->
|
url: () ->
|
||||||
url = "/project/#{@options.project_id}/doc/#{@options.doc_id}/updates?limit=#{@batchSize}"
|
url = "/project/#{@options.project_id}/doc/#{@options.doc_id}/updates?limit=#{@batchSize}"
|
||||||
if @models.length > 0
|
if @models.length > 0
|
||||||
last = @models[@models.length - 1]
|
last = @models[@models.length - 1]
|
||||||
url += "&to=#{last.get("start_ts") - 1}"
|
url += "&to=#{last.get("version") - 1}"
|
||||||
return url
|
return url
|
||||||
|
|
||||||
parse: (json) ->
|
parse: (json) ->
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
define [
|
||||||
|
"libs/backbone"
|
||||||
|
], ()->
|
||||||
|
Diff = Backbone.Model.extend
|
||||||
|
url: () ->
|
||||||
|
"/project/#{@get("project_id")}/doc/#{@get("doc_id")}/diff?from=#{@get("from")}&to=#{@get("to")}"
|
|
@ -5,10 +5,18 @@
|
||||||
.track-changes-diff {
|
.track-changes-diff {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: @versionsListWidth + 1px;
|
right: @versionsListWidth + 1px;
|
||||||
right: 0;
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
padding: 0px 12px;
|
padding: 0px 12px;
|
||||||
overflow: scroll;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
.ace_editor {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-changes-side-bar {
|
.track-changes-side-bar {
|
||||||
|
@ -27,4 +35,19 @@
|
||||||
top: 0px;
|
top: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.deleted-change-background, .deleted-change-foreground, .inserted-change, .change-name-marker {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-name-marker {
|
||||||
|
.name {
|
||||||
|
font-size: 0.8em;
|
||||||
|
padding: 2px 6px;
|
||||||
|
.border-radius(3px 3px 3px 3px);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue