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; |