Commit e1282d507f1a0321c4f25815470b0fa05265e6dd
1 parent
40576b87
Exists in
master
and in
4 other branches
BranchGraph now loads async
Centralized keyboard and drag events for BranchGraph
Showing
6 changed files
with
122 additions
and
94 deletions
Show diff stats
app/assets/javascripts/projects.js.coffee
| @@ -18,10 +18,3 @@ $ -> | @@ -18,10 +18,3 @@ $ -> | ||
| 18 | # Ref switcher | 18 | # Ref switcher |
| 19 | $('.project-refs-select').on 'change', -> | 19 | $('.project-refs-select').on 'change', -> |
| 20 | $(@).parents('form').submit() | 20 | $(@).parents('form').submit() |
| 21 | - | ||
| 22 | -class @GraphNav | ||
| 23 | - @init: -> | ||
| 24 | - $('.graph svg').css 'position', 'relative' | ||
| 25 | - $('body').bind 'keyup', (e) -> | ||
| 26 | - $('.graph svg').animate(left: '+=400') if e.keyCode is 37 # left | ||
| 27 | - $('.graph svg').animate(left: '-=400') if e.keyCode is 39 # right |
app/controllers/projects_controller.rb
| @@ -83,9 +83,19 @@ class ProjectsController < ProjectResourceController | @@ -83,9 +83,19 @@ class ProjectsController < ProjectResourceController | ||
| 83 | end | 83 | end |
| 84 | 84 | ||
| 85 | def graph | 85 | def graph |
| 86 | - graph = Gitlab::Graph::JsonBuilder.new(project) | 86 | + |
| 87 | + respond_to do |format| | ||
| 88 | + format.html | ||
| 89 | + format.json do | ||
| 90 | + graph = Gitlab::Graph::JsonBuilder.new(project) | ||
| 91 | + #@days_json, @commits_json = graph.days_json, graph.commits_json | ||
| 92 | + render :text => graph.to_json | ||
| 93 | + end | ||
| 94 | + end | ||
| 95 | + | ||
| 96 | + | ||
| 87 | 97 | ||
| 88 | - @days_json, @commits_json = graph.days_json, graph.commits_json | 98 | + |
| 89 | end | 99 | end |
| 90 | 100 | ||
| 91 | def destroy | 101 | def destroy |
app/views/projects/graph.html.haml
| @@ -4,12 +4,10 @@ | @@ -4,12 +4,10 @@ | ||
| 4 | %h4 | 4 | %h4 |
| 5 | %small You can move around the graph by using the arrow keys. | 5 | %small You can move around the graph by using the arrow keys. |
| 6 | #holder.graph | 6 | #holder.graph |
| 7 | + .loading | ||
| 7 | 8 | ||
| 8 | :javascript | 9 | :javascript |
| 9 | - var commits = #{@commits_json} | ||
| 10 | - , days = #{@days_json}; | ||
| 11 | - var branch_graph = new BranchGraph(days, commits); | 10 | + var branch_graph; |
| 12 | $(function(){ | 11 | $(function(){ |
| 13 | - branch_graph.buildGraph($("#holder")[0]); | ||
| 14 | - GraphNav.init(); | 12 | + branch_graph = new BranchGraph($("#holder"), '#{url_for :controller => 'projects', :action => 'graph'}'); |
| 15 | }); | 13 | }); |
lib/gitlab/graph/commit.rb
| @@ -28,7 +28,7 @@ module Gitlab | @@ -28,7 +28,7 @@ module Gitlab | ||
| 28 | h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil? | 28 | h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil? |
| 29 | h[:id] = sha | 29 | h[:id] = sha |
| 30 | h[:date] = date | 30 | h[:date] = date |
| 31 | - h[:message] = escape_once(message) | 31 | + h[:message] = message |
| 32 | h[:login] = author.email | 32 | h[:login] = author.email |
| 33 | h | 33 | h |
| 34 | end | 34 | end |
lib/gitlab/graph/json_builder.rb
| @@ -17,16 +17,15 @@ module Gitlab | @@ -17,16 +17,15 @@ module Gitlab | ||
| 17 | @commits = collect_commits | 17 | @commits = collect_commits |
| 18 | @days = index_commits | 18 | @days = index_commits |
| 19 | end | 19 | end |
| 20 | - | ||
| 21 | - def days_json | ||
| 22 | - @days_json = @days.compact.map { |d| [d.day, d.strftime("%b")] }.to_json | ||
| 23 | - end | ||
| 24 | - | ||
| 25 | - def commits_json | ||
| 26 | - @commits_json = @commits.map(&:to_graph_hash).to_json | 20 | + |
| 21 | + def to_json | ||
| 22 | + { | ||
| 23 | + days: @days.compact.map { |d| [d.day, d.strftime("%b")] }, | ||
| 24 | + commits: @commits.map(&:to_graph_hash) | ||
| 25 | + }.to_json | ||
| 27 | end | 26 | end |
| 28 | - | ||
| 29 | - protected | 27 | + |
| 28 | + protected | ||
| 30 | 29 | ||
| 31 | # Get commits from repository | 30 | # Get commits from repository |
| 32 | # | 31 | # |
vendor/assets/javascripts/branch-graph.js
| 1 | !function(){ | 1 | !function(){ |
| 2 | 2 | ||
| 3 | - var BranchGraph = function(days, commits){ | 3 | + var BranchGraph = function(element, url){ |
| 4 | + this.element = element; | ||
| 5 | + this.url = url; | ||
| 4 | 6 | ||
| 5 | - this.days = days || {}; | ||
| 6 | - this.commits = commits || {}; | ||
| 7 | this.comms = {}; | 7 | this.comms = {}; |
| 8 | - this.pixelsX = []; | ||
| 9 | - this.pixelsY = []; | ||
| 10 | this.mtime = 0; | 8 | this.mtime = 0; |
| 11 | this.mspace = 0; | 9 | this.mspace = 0; |
| 12 | this.parents = {}; | 10 | this.parents = {}; |
| 13 | - this.ii = 0; | ||
| 14 | this.colors = ["#000"]; | 11 | this.colors = ["#000"]; |
| 15 | 12 | ||
| 16 | - this.prepareData(); | 13 | + this.load(); |
| 17 | }; | 14 | }; |
| 18 | 15 | ||
| 19 | - BranchGraph.prototype.prepareData = function(){ | 16 | + BranchGraph.prototype.load = function(){ |
| 17 | + $.ajax({ | ||
| 18 | + url: this.url, | ||
| 19 | + method: 'get', | ||
| 20 | + dataType: 'json', | ||
| 21 | + success: $.proxy(function(data){ | ||
| 22 | + $('.loading', this.element).hide(); | ||
| 23 | + this.prepareData(data.days, data.commits); | ||
| 24 | + this.buildGraph(this.element.get(0)); | ||
| 25 | + }, this) | ||
| 26 | + }); | ||
| 27 | + }, | ||
| 28 | + | ||
| 29 | + BranchGraph.prototype.prepareData = function(days, commits){ | ||
| 30 | + this.days = days; | ||
| 31 | + this.commits = commits; | ||
| 20 | ii = this.commits.length; | 32 | ii = this.commits.length; |
| 21 | for (var i = 0; i < ii; i++) { | 33 | for (var i = 0; i < ii; i++) { |
| 22 | for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) { | 34 | for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) { |
| @@ -25,8 +37,8 @@ | @@ -25,8 +37,8 @@ | ||
| 25 | this.mtime = Math.max(this.mtime, this.commits[i].time); | 37 | this.mtime = Math.max(this.mtime, this.commits[i].time); |
| 26 | this.mspace = Math.max(this.mspace, this.commits[i].space); | 38 | this.mspace = Math.max(this.mspace, this.commits[i].space); |
| 27 | } | 39 | } |
| 28 | - this.mtime = this.mtime + 4; | ||
| 29 | - this.mspace = this.mspace + 10; | 40 | + this.mtime += 4; |
| 41 | + this.mspace += 10; | ||
| 30 | for (i = 0; i < ii; i++) { | 42 | for (i = 0; i < ii; i++) { |
| 31 | if (this.commits[i].id in this.parents) { | 43 | if (this.commits[i].id in this.parents) { |
| 32 | this.commits[i].isParent = true; | 44 | this.commits[i].isParent = true; |
| @@ -41,10 +53,13 @@ | @@ -41,10 +53,13 @@ | ||
| 41 | BranchGraph.prototype.buildGraph = function(holder){ | 53 | BranchGraph.prototype.buildGraph = function(holder){ |
| 42 | var ch = this.mspace * 20 + 20 | 54 | var ch = this.mspace * 20 + 20 |
| 43 | , cw = this.mtime * 20 + 20 | 55 | , cw = this.mtime * 20 + 20 |
| 44 | - , r = Raphael("holder", cw, ch) | 56 | + , r = Raphael(holder, cw, ch) |
| 45 | , top = r.set() | 57 | , top = r.set() |
| 46 | , cuday = 0 | 58 | , cuday = 0 |
| 47 | - , cumonth = ""; | 59 | + , cumonth = "" |
| 60 | + , r; | ||
| 61 | + | ||
| 62 | + this.raphael = r; | ||
| 48 | 63 | ||
| 49 | r.rect(0, 0, this.days.length * 20 + 80, 30).attr({fill: "#222"}); | 64 | r.rect(0, 0, this.days.length * 20 + 80, 30).attr({fill: "#222"}); |
| 50 | r.rect(0, 30, this.days.length * 20 + 80, 20).attr({fill: "#444"}); | 65 | r.rect(0, 30, this.days.length * 20 + 80, 20).attr({fill: "#444"}); |
| @@ -116,66 +131,79 @@ | @@ -116,66 +131,79 @@ | ||
| 116 | } | 131 | } |
| 117 | } | 132 | } |
| 118 | } | 133 | } |
| 119 | - (function (c, x, y) { | ||
| 120 | - top.push(r.circle(x, y, 10).attr({ | ||
| 121 | - fill: "#000", | ||
| 122 | - opacity: 0, | ||
| 123 | - cursor: "pointer" | ||
| 124 | - }) | ||
| 125 | - .click(function(){ | ||
| 126 | - location.href = location.href.replace("graph", "commits/" + c.id); | ||
| 127 | - }) | ||
| 128 | - .hover(function () { | ||
| 129 | - // Create empty node to convert entities to character | ||
| 130 | - var m = $('<div />').html(c.message).text() | ||
| 131 | - , s = r.text(100, 100, c.author + "\n \n" + c.id + "\n \n" + m).attr({ | ||
| 132 | - fill: "#fff" | ||
| 133 | - }); | ||
| 134 | - this.popup = r.popupit(x, y + 5, s, 0); | ||
| 135 | - top.push(this.popup.insertBefore(this)); | ||
| 136 | - }, function () { | ||
| 137 | - this.popup && this.popup.remove() && delete this.popup; | ||
| 138 | - })); | ||
| 139 | - }(this.commits[i], x, y)); | ||
| 140 | - | ||
| 141 | - top.toFront(); | ||
| 142 | - var hw = holder.offsetWidth | ||
| 143 | - , hh = holder.offsetHeight | ||
| 144 | - , v = r.rect(hw - 8, 0, 4, Math.pow(hh, 2) / ch, 2).attr({ | ||
| 145 | - fill: "#000", | ||
| 146 | - opacity: 0 | ||
| 147 | - }) | ||
| 148 | - , h = r.rect(0, hh - 8, Math.pow(hw, 2) / cw, 4, 2).attr({ | ||
| 149 | - fill: "#000", | ||
| 150 | - opacity: 0 | ||
| 151 | - }) | ||
| 152 | - , bars = r.set(v, h) | ||
| 153 | - , drag | ||
| 154 | - , dragger = function (event) { | ||
| 155 | - if (drag) { | ||
| 156 | - event = event || window.event; | ||
| 157 | - holder.scrollLeft = drag.sl - (event.clientX - drag.x); | ||
| 158 | - holder.scrollTop = drag.st - (event.clientY - drag.y); | ||
| 159 | - } | ||
| 160 | - }; | ||
| 161 | - holder.onmousedown = function (event) { | ||
| 162 | - event = event || window.event; | ||
| 163 | - drag = { | ||
| 164 | - x: event.clientX, | ||
| 165 | - y: event.clientY, | ||
| 166 | - st: holder.scrollTop, | ||
| 167 | - sl: holder.scrollLeft | ||
| 168 | - }; | ||
| 169 | - document.onmousemove = dragger; | ||
| 170 | - bars.animate({opacity: .5}, 300); | 134 | + this.appendAnchor(top, this.commits[i], x, y); |
| 135 | + } | ||
| 136 | + top.toFront(); | ||
| 137 | + var hw = holder.offsetWidth | ||
| 138 | + , hh = holder.offsetHeight | ||
| 139 | + , v = r.rect(hw - 8, 0, 4, Math.pow(hh, 2) / ch, 2).attr({ | ||
| 140 | + fill: "#000", | ||
| 141 | + opacity: 0 | ||
| 142 | + }) | ||
| 143 | + , h = r.rect(0, hh - 8, Math.pow(hw, 2) / cw, 4, 2).attr({ | ||
| 144 | + fill: "#000", | ||
| 145 | + opacity: 0 | ||
| 146 | + }) | ||
| 147 | + , bars = r.set(v, h) | ||
| 148 | + , drag | ||
| 149 | + , dragger = function (event) { | ||
| 150 | + if (drag) { | ||
| 151 | + event = event || window.event; | ||
| 152 | + holder.scrollLeft = drag.sl - (event.clientX - drag.x); | ||
| 153 | + holder.scrollTop = drag.st - (event.clientY - drag.y); | ||
| 154 | + } | ||
| 171 | }; | 155 | }; |
| 172 | - document.onmouseup = function () { | ||
| 173 | - drag = false; | ||
| 174 | - document.onmousemove = null; | ||
| 175 | - bars.animate({opacity: 0}, 300); | 156 | + holder.onmousedown = function (event) { |
| 157 | + event = event || window.event; | ||
| 158 | + drag = { | ||
| 159 | + x: event.clientX, | ||
| 160 | + y: event.clientY, | ||
| 161 | + st: holder.scrollTop, | ||
| 162 | + sl: holder.scrollLeft | ||
| 176 | }; | 163 | }; |
| 177 | - holder.scrollLeft = cw; | ||
| 178 | - } | 164 | + document.onmousemove = dragger; |
| 165 | + bars.animate({opacity: .5}, 300); | ||
| 166 | + }; | ||
| 167 | + document.onmouseup = function () { | ||
| 168 | + drag = false; | ||
| 169 | + document.onmousemove = null; | ||
| 170 | + bars.animate({opacity: 0}, 300); | ||
| 171 | + }; | ||
| 172 | + | ||
| 173 | + $(window).on('keydown', function(event){ | ||
| 174 | + if(event.keyCode == 37){ | ||
| 175 | + holder.scrollLeft -= 50; | ||
| 176 | + } | ||
| 177 | + if(event.keyCode == 39){ | ||
| 178 | + // right | ||
| 179 | + holder.scrollLeft += 50; | ||
| 180 | + } | ||
| 181 | + }); | ||
| 182 | + | ||
| 183 | + | ||
| 184 | + holder.scrollLeft = cw; | ||
| 185 | + }; | ||
| 186 | + | ||
| 187 | + BranchGraph.prototype.appendAnchor = function(top, c, x, y) { | ||
| 188 | + var r = this.raphael; | ||
| 189 | + top.push(r.circle(x, y, 10).attr({ | ||
| 190 | + fill: "#000", | ||
| 191 | + opacity: 0, | ||
| 192 | + cursor: "pointer" | ||
| 193 | + }) | ||
| 194 | + .click(function(){ | ||
| 195 | + location.href = location.href.replace("graph", "commits/" + c.id); | ||
| 196 | + }) | ||
| 197 | + .hover(function () { | ||
| 198 | + // Create empty node to convert entities to character | ||
| 199 | + var s = r.text(100, 100, c.author + "\n \n" + c.id + "\n \n" + c.message).attr({ | ||
| 200 | + fill: "#fff" | ||
| 201 | + }); | ||
| 202 | + this.popup = r.popupit(x, y + 5, s, 0); | ||
| 203 | + top.push(this.popup.insertBefore(this)); | ||
| 204 | + }, function () { | ||
| 205 | + this.popup && this.popup.remove() && delete this.popup; | ||
| 206 | + })); | ||
| 179 | }; | 207 | }; |
| 180 | 208 | ||
| 181 | this.BranchGraph = BranchGraph; | 209 | this.BranchGraph = BranchGraph; |