Explorar el Código

Show nice diffs using ace and markers

James Allen hace 12 años
padre
commit
1a91036bb6

+ 10 - 2
services/web/public/coffee/track-changes/ChangeListView.coffee

@@ -1,5 +1,4 @@
 define [
-	"history/util"
 	"libs/mustache"
 	"libs/backbone"
 ], (util)->
@@ -9,7 +8,7 @@ define [
 		events:
 			"scroll" : "loadUntilFull"
 
-		initialize: ->
+		initialize: () ->
 			@itemViews = []
 			@atEndOfCollection = false
 
@@ -34,6 +33,8 @@ define [
 			index = @collection.indexOf(model)
 			elementAtIndex = @$(".change-list").children()[index]
 			view.$el.insertBefore(elementAtIndex)
+			view.on "click", (e, v) =>
+				@trigger "change_diff", v.model.get("version")
 
 		listShorterThanContainer: ->
 			@$el.height() > @$(".change-list").height()
@@ -81,6 +82,9 @@ define [
 	
 	ChangeListItemView = Backbone.View.extend
 		tagName: "li"
+
+		events:
+			"click a": "onClick"
 	
 		template : $("#changeListItemTemplate").html()
 
@@ -97,5 +101,9 @@ define [
 			# modelView.end_ts = util.formatDate(modelView.end_ts)
 			return modelView
 
+		onClick: (e) ->
+			e.preventDefault()
+			@trigger "click", e, @
+
 	return ChangeListView
 

+ 139 - 0
services/web/public/coffee/track-changes/DiffView.coffee

@@ -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
+

+ 19 - 4
services/web/public/coffee/track-changes/TrackChangesManager.coffee

@@ -1,7 +1,9 @@
 define [
 	"track-changes/models/ChangeList"
+	"track-changes/models/Diff"
 	"track-changes/ChangeListView"
-], (ChangeList, ChangeListView) ->
+	"track-changes/DiffView"
+], (ChangeList, Diff, ChangeListView, DiffView) ->
 	class TrackChangesManager
 		template: $("#trackChangesPanelTemplate").html()
 		
@@ -11,9 +13,9 @@ define [
 			@hideEl()
 
 		show: () ->
-			project_id = window.userSettings.project_id
-			doc_id = @ide.editor.current_doc_id
-			@changes = new ChangeList([], doc_id: doc_id, project_id: project_id)
+			@project_id = window.userSettings.project_id
+			@doc_id = @ide.editor.current_doc_id
+			@changes = new ChangeList([], doc_id: @doc_id, project_id: @project_id)
 
 			@changeListView = new ChangeListView(
 				collection : @changes,
@@ -22,6 +24,19 @@ define [
 			@changeListView.render()
 			@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: ->

+ 1 - 0
services/web/public/coffee/track-changes/models/Change.coffee

@@ -7,4 +7,5 @@ define [
 				start_ts: change.meta.start_ts
 				end_ts: change.meta.end_ts
 				user_id: change.meta.user_id
+				version: change.v
 			}

+ 1 - 2
services/web/public/coffee/track-changes/models/ChangeList.coffee

@@ -7,13 +7,12 @@ define [
 		batchSize: 3
 
 		initialize: (models, @options) ->
-			console.log arguments
 
 		url: () ->
 			url = "/project/#{@options.project_id}/doc/#{@options.doc_id}/updates?limit=#{@batchSize}"
 			if @models.length > 0
 				last = @models[@models.length - 1]
-				url += "&to=#{last.get("start_ts") - 1}"
+				url += "&to=#{last.get("version") - 1}"
 			return url
 
 		parse: (json) ->

+ 6 - 0
services/web/public/coffee/track-changes/models/Diff.coffee

@@ -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")}"

+ 25 - 2
services/web/public/stylesheets/less/trackchanges.less

@@ -5,10 +5,18 @@
 	.track-changes-diff {
 		position: absolute;
 		right: @versionsListWidth + 1px;
-		right: 0;
+		left: 0;
+		top: 0;
+		bottom: 0;
 		padding: 0px 12px;
-		overflow: scroll;
 		height: 100%;
+		.ace_editor {
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+		}
 	}
 
 	.track-changes-side-bar {
@@ -27,4 +35,19 @@
 		top: 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;
+		}
+	}
 }