Merge pull request #3258 from hiroponz/display-commit-msg
Display commit message on network graph.
This commit is contained in:
commit
d6338a8482
4 changed files with 132 additions and 103 deletions
|
@ -5,6 +5,10 @@ class BranchGraph
|
||||||
@mspace = 0
|
@mspace = 0
|
||||||
@parents = {}
|
@parents = {}
|
||||||
@colors = ["#000"]
|
@colors = ["#000"]
|
||||||
|
@offsetX = 120
|
||||||
|
@offsetY = 20
|
||||||
|
@unitTime = 30
|
||||||
|
@unitSpace = 10
|
||||||
@load()
|
@load()
|
||||||
|
|
||||||
load: ->
|
load: ->
|
||||||
|
@ -20,8 +24,6 @@ class BranchGraph
|
||||||
|
|
||||||
prepareData: (@days, @commits) ->
|
prepareData: (@days, @commits) ->
|
||||||
@collectParents()
|
@collectParents()
|
||||||
@mtime += 4
|
|
||||||
@mspace += 10
|
|
||||||
|
|
||||||
for c in @commits
|
for c in @commits
|
||||||
c.isParent = true if c.id of @parents
|
c.isParent = true if c.id of @parents
|
||||||
|
@ -35,6 +37,7 @@ class BranchGraph
|
||||||
@mspace = Math.max(@mspace, c.space)
|
@mspace = Math.max(@mspace, c.space)
|
||||||
for p in c.parents
|
for p in c.parents
|
||||||
@parents[p[0]] = true
|
@parents[p[0]] = true
|
||||||
|
@mspace = Math.max(@mspace, p[1])
|
||||||
|
|
||||||
collectColors: ->
|
collectColors: ->
|
||||||
k = 0
|
k = 0
|
||||||
|
@ -46,25 +49,23 @@ class BranchGraph
|
||||||
k++
|
k++
|
||||||
|
|
||||||
buildGraph: ->
|
buildGraph: ->
|
||||||
|
graphHeight = $(@element).height()
|
||||||
graphWidth = $(@element).width()
|
graphWidth = $(@element).width()
|
||||||
ch = @mspace * 20 + 100
|
ch = Math.max(graphHeight, @unitTime * @mtime + 100)
|
||||||
cw = Math.max(graphWidth, @mtime * 20 + 260)
|
cw = Math.max(graphWidth, @unitSpace * @mspace + 260)
|
||||||
r = Raphael(@element.get(0), cw, ch)
|
@r = r = Raphael(@element.get(0), cw, ch)
|
||||||
top = r.set()
|
top = r.set()
|
||||||
cuday = 0
|
cuday = 0
|
||||||
cumonth = ""
|
cumonth = ""
|
||||||
offsetX = 20
|
barHeight = Math.max(graphHeight, @unitTime * @days.length + 320)
|
||||||
offsetY = 60
|
|
||||||
barWidth = Math.max(graphWidth, @days.length * 20 + 320)
|
r.rect(0, 0, 20, barHeight).attr fill: "#222"
|
||||||
scrollLeft = cw
|
r.rect(20, 0, 20, barHeight).attr fill: "#444"
|
||||||
@raphael = r
|
|
||||||
r.rect(0, 0, barWidth, 20).attr fill: "#222"
|
|
||||||
r.rect(0, 20, barWidth, 20).attr fill: "#444"
|
|
||||||
|
|
||||||
for day, mm in @days
|
for day, mm in @days
|
||||||
if cuday isnt day[0]
|
if cuday isnt day[0]
|
||||||
# Dates
|
# Dates
|
||||||
r.text(offsetX + mm * 20, 31, day[0])
|
r.text(30, @offsetY + @unitTime * mm, day[0])
|
||||||
.attr(
|
.attr(
|
||||||
font: "12px Monaco, monospace"
|
font: "12px Monaco, monospace"
|
||||||
fill: "#DDD"
|
fill: "#DDD"
|
||||||
|
@ -73,7 +74,7 @@ class BranchGraph
|
||||||
|
|
||||||
if cumonth isnt day[1]
|
if cumonth isnt day[1]
|
||||||
# Months
|
# Months
|
||||||
r.text(offsetX + mm * 20, 11, day[1])
|
r.text(10, @offsetY + @unitTime * mm, day[1])
|
||||||
.attr(
|
.attr(
|
||||||
font: "12px Monaco, monospace"
|
font: "12px Monaco, monospace"
|
||||||
fill: "#EEE"
|
fill: "#EEE"
|
||||||
|
@ -81,61 +82,20 @@ class BranchGraph
|
||||||
cumonth = day[1]
|
cumonth = day[1]
|
||||||
|
|
||||||
for commit in @commits
|
for commit in @commits
|
||||||
x = offsetX + 20 * commit.time
|
x = @offsetX + @unitSpace * (@mspace - commit.space)
|
||||||
y = offsetY + 10 * commit.space
|
y = @offsetY + @unitTime * commit.time
|
||||||
# Draw dot
|
|
||||||
r.circle(x, y, 3).attr(
|
|
||||||
fill: @colors[commit.space]
|
|
||||||
stroke: "none"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Draw lines
|
@drawDot(x, y, commit)
|
||||||
for parent in commit.parents
|
|
||||||
parentCommit = @preparedCommits[parent[0]]
|
|
||||||
parentX = offsetX + 20 * parentCommit.time
|
|
||||||
parentY1 = offsetY + 10 * parentCommit.space
|
|
||||||
parentY2 = offsetY + 10 * parent[1]
|
|
||||||
if parentCommit.space is commit.space and parentCommit.space is parent[1]
|
|
||||||
r.path(["M", x, y, "L", parentX, parentY1]).attr(
|
|
||||||
stroke: @colors[parentCommit.space]
|
|
||||||
"stroke-width": 2
|
|
||||||
)
|
|
||||||
|
|
||||||
else if parentCommit.space < commit.space
|
@drawLines(x, y, commit)
|
||||||
if y is parentY2
|
|
||||||
r.path(["M", x - 5, y, "l-5,-2,0,4,5,-2", "L", x - 10, y, "L", x - 15, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr(
|
|
||||||
stroke: @colors[commit.space]
|
|
||||||
"stroke-width": 2
|
|
||||||
)
|
|
||||||
|
|
||||||
else
|
@appendLabel(x, y, commit.refs) if commit.refs
|
||||||
r.path(["M", x - 3, y - 6, "l-4,-3,4,-2,0,5", "L", x - 5, y - 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr(
|
|
||||||
stroke: @colors[commit.space]
|
|
||||||
"stroke-width": 2
|
|
||||||
)
|
|
||||||
|
|
||||||
else
|
@appendAnchor(top, commit, x, y)
|
||||||
r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5", "L", x - 5, y + 10, "L", x - 10, parentY2, "L", parentX + 5, parentY2, "L", parentX, parentY1]).attr(
|
|
||||||
stroke: @colors[parentCommit.space]
|
|
||||||
"stroke-width": 2
|
|
||||||
)
|
|
||||||
|
|
||||||
@appendLabel x, y, commit.refs if commit.refs
|
@markCommit(x, y, commit, graphHeight)
|
||||||
|
|
||||||
# Mark commit and displayed in the center
|
|
||||||
if commit.id is @options.commit_id
|
|
||||||
r.path(["M", x, y - 5, "L", x + 4, y - 15, "L", x - 4, y - 15, "Z"]).attr(
|
|
||||||
fill: "#000"
|
|
||||||
"fill-opacity": .7
|
|
||||||
stroke: "none"
|
|
||||||
)
|
|
||||||
|
|
||||||
scrollLeft = x - graphWidth / 2
|
|
||||||
|
|
||||||
@appendAnchor top, commit, x, y
|
|
||||||
|
|
||||||
top.toFront()
|
top.toFront()
|
||||||
@element.scrollLeft scrollLeft
|
|
||||||
@bindEvents()
|
@bindEvents()
|
||||||
|
|
||||||
bindEvents: ->
|
bindEvents: ->
|
||||||
|
@ -167,35 +127,37 @@ class BranchGraph
|
||||||
element.scrollTop element.scrollTop() + 50 if event.keyCode is 40
|
element.scrollTop element.scrollTop() + 50 if event.keyCode is 40
|
||||||
|
|
||||||
appendLabel: (x, y, refs) ->
|
appendLabel: (x, y, refs) ->
|
||||||
r = @raphael
|
r = @r
|
||||||
shortrefs = refs
|
shortrefs = refs
|
||||||
# Truncate if longer than 15 chars
|
# Truncate if longer than 15 chars
|
||||||
shortrefs = shortrefs.substr(0, 15) + "…" if shortrefs.length > 17
|
shortrefs = shortrefs.substr(0, 15) + "…" if shortrefs.length > 17
|
||||||
text = r.text(x + 5, y + 8 + 10, shortrefs).attr(
|
text = r.text(x + 8, y, shortrefs).attr(
|
||||||
|
"text-anchor": "start"
|
||||||
font: "10px Monaco, monospace"
|
font: "10px Monaco, monospace"
|
||||||
fill: "#FFF"
|
fill: "#FFF"
|
||||||
title: refs
|
title: refs
|
||||||
)
|
)
|
||||||
textbox = text.getBBox()
|
textbox = text.getBBox()
|
||||||
text.transform ["t", textbox.height / -4, textbox.width / 2 + 5, "r90"]
|
|
||||||
# Create rectangle based on the size of the textbox
|
# Create rectangle based on the size of the textbox
|
||||||
rect = r.rect(x, y, textbox.width + 15, textbox.height + 5, 4).attr(
|
rect = r.rect(x, y - 7, textbox.width + 15, textbox.height + 5, 4).attr(
|
||||||
fill: "#000"
|
fill: "#000"
|
||||||
"fill-opacity": .7
|
"fill-opacity": .5
|
||||||
stroke: "none"
|
stroke: "none"
|
||||||
)
|
)
|
||||||
triangle = r.path(["M", x, y + 5, "L", x + 4, y + 15, "L", x - 4, y + 15, "Z"]).attr(
|
triangle = r.path(["M", x - 5, y, "L", x - 15, y - 4, "L", x - 15, y + 4, "Z"]).attr(
|
||||||
fill: "#000"
|
fill: "#000"
|
||||||
"fill-opacity": .7
|
"fill-opacity": .5
|
||||||
stroke: "none"
|
stroke: "none"
|
||||||
)
|
)
|
||||||
# Rotate and reposition rectangle over text
|
|
||||||
rect.transform ["r", 90, x, y, "t", 15, -9]
|
label = r.set(rect, text)
|
||||||
|
label.transform(["t", -rect.getBBox().width - 15, 0])
|
||||||
|
|
||||||
# Set text to front
|
# Set text to front
|
||||||
text.toFront()
|
text.toFront()
|
||||||
|
|
||||||
appendAnchor: (top, commit, x, y) ->
|
appendAnchor: (top, commit, x, y) ->
|
||||||
r = @raphael
|
r = @r
|
||||||
options = @options
|
options = @options
|
||||||
anchor = r.circle(x, y, 10).attr(
|
anchor = r.circle(x, y, 10).attr(
|
||||||
fill: "#000"
|
fill: "#000"
|
||||||
|
@ -204,18 +166,95 @@ class BranchGraph
|
||||||
).click(->
|
).click(->
|
||||||
window.open options.commit_url.replace("%s", commit.id), "_blank"
|
window.open options.commit_url.replace("%s", commit.id), "_blank"
|
||||||
).hover(->
|
).hover(->
|
||||||
@tooltip = r.commitTooltip(x, y + 5, commit)
|
@tooltip = r.commitTooltip(x + 5, y, commit)
|
||||||
top.push @tooltip.insertBefore(this)
|
top.push @tooltip.insertBefore(this)
|
||||||
, ->
|
, ->
|
||||||
@tooltip and @tooltip.remove() and delete @tooltip
|
@tooltip and @tooltip.remove() and delete @tooltip
|
||||||
)
|
)
|
||||||
top.push anchor
|
top.push anchor
|
||||||
|
|
||||||
|
drawDot: (x, y, commit) ->
|
||||||
|
r = @r
|
||||||
|
r.circle(x, y, 3).attr(
|
||||||
|
fill: @colors[commit.space]
|
||||||
|
stroke: "none"
|
||||||
|
)
|
||||||
|
r.rect(@offsetX + @unitSpace * @mspace + 10, y - 10, 20, 20).attr(
|
||||||
|
fill: "url(#{commit.author.icon})"
|
||||||
|
stroke: @colors[commit.space]
|
||||||
|
"stroke-width": 2
|
||||||
|
)
|
||||||
|
r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr(
|
||||||
|
"text-anchor": "start"
|
||||||
|
font: "14px Monaco, monospace"
|
||||||
|
)
|
||||||
|
|
||||||
|
drawLines: (x, y, commit) ->
|
||||||
|
r = @r
|
||||||
|
for parent in commit.parents
|
||||||
|
parentCommit = @preparedCommits[parent[0]]
|
||||||
|
parentY = @offsetY + @unitTime * parentCommit.time
|
||||||
|
parentX1 = @offsetX + @unitSpace * (@mspace - parentCommit.space)
|
||||||
|
parentX2 = @offsetX + @unitSpace * (@mspace - parent[1])
|
||||||
|
|
||||||
|
if parentCommit.space is commit.space and parentCommit.space is parent[1]
|
||||||
|
r.path(["M", x, y, "L", parentX1, parentY]).attr(
|
||||||
|
stroke: @colors[parentCommit.space]
|
||||||
|
"stroke-width": 2
|
||||||
|
)
|
||||||
|
|
||||||
|
else if parentCommit.space < commit.space
|
||||||
|
if x is parentX2
|
||||||
|
r
|
||||||
|
.path([
|
||||||
|
"M", x, y + 5,
|
||||||
|
"l-2,5,4,0,-2,-5",
|
||||||
|
"L", x, y + 10,
|
||||||
|
"L", parentX2, y + 10,
|
||||||
|
"L", parentX2, parentY - 5,
|
||||||
|
"L", parentX1, parentY])
|
||||||
|
.attr(
|
||||||
|
stroke: @colors[commit.space]
|
||||||
|
"stroke-width": 2)
|
||||||
|
|
||||||
|
else
|
||||||
|
r
|
||||||
|
.path([
|
||||||
|
"M", x + 3, y + 3,
|
||||||
|
"l5,0,-2,4,-3,-4",
|
||||||
|
"L", x + 7, y + 5,
|
||||||
|
"L", parentX2, y + 10,
|
||||||
|
"L", parentX2, parentY - 5,
|
||||||
|
"L", parentX1, parentY])
|
||||||
|
.attr(
|
||||||
|
stroke: @colors[commit.space]
|
||||||
|
"stroke-width": 2)
|
||||||
|
|
||||||
|
else
|
||||||
|
r
|
||||||
|
.path([
|
||||||
|
"M", x - 3, y + 3,
|
||||||
|
"l-5,0,2,4,3,-4",
|
||||||
|
"L", x - 7, y + 5,
|
||||||
|
"L", parentX2, y + 10,
|
||||||
|
"L", parentX2, parentY - 5,
|
||||||
|
"L", parentX1, parentY])
|
||||||
|
.attr(
|
||||||
|
stroke: @colors[parentCommit.space]
|
||||||
|
"stroke-width": 2)
|
||||||
|
|
||||||
|
markCommit: (x, y, commit, graphHeight) ->
|
||||||
|
if commit.id is @options.commit_id
|
||||||
|
r = @r
|
||||||
|
r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr(
|
||||||
|
fill: "#000"
|
||||||
|
"fill-opacity": .5
|
||||||
|
stroke: "none"
|
||||||
|
)
|
||||||
|
# Displayed in the center
|
||||||
|
@element.scrollTop(y - graphHeight / 2)
|
||||||
|
|
||||||
Raphael::commitTooltip = (x, y, commit) ->
|
Raphael::commitTooltip = (x, y, commit) ->
|
||||||
icon = undefined
|
|
||||||
nameText = undefined
|
|
||||||
idText = undefined
|
|
||||||
messageText = undefined
|
|
||||||
boxWidth = 300
|
boxWidth = 300
|
||||||
boxHeight = 200
|
boxHeight = 200
|
||||||
icon = @image(commit.author.icon, x, y, 20, 20)
|
icon = @image(commit.author.icon, x, y, 20, 20)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
.graph {
|
.graph {
|
||||||
background: #f1f1f1;
|
background: #f1f1f1;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
height: 70%;
|
height: 500px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,12 @@ module Network
|
||||||
def index_commits
|
def index_commits
|
||||||
days = []
|
days = []
|
||||||
@map = {}
|
@map = {}
|
||||||
|
@reserved = {}
|
||||||
|
|
||||||
@commits.reverse.each_with_index do |c,i|
|
@commits.each_with_index do |c,i|
|
||||||
c.time = i
|
c.time = i
|
||||||
days[i] = c.committed_date
|
days[i] = c.committed_date
|
||||||
@map[c.id] = c
|
@map[c.id] = c
|
||||||
end
|
|
||||||
|
|
||||||
@reserved = {}
|
|
||||||
days.each_index do |i|
|
|
||||||
@reserved[i] = []
|
@reserved[i] = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -135,11 +132,7 @@ module Network
|
||||||
spaces = []
|
spaces = []
|
||||||
|
|
||||||
commit.parents(@map).each do |parent|
|
commit.parents(@map).each do |parent|
|
||||||
range = if commit.time < parent.time then
|
range = commit.time..parent.time
|
||||||
commit.time..parent.time
|
|
||||||
else
|
|
||||||
parent.time..commit.time
|
|
||||||
end
|
|
||||||
|
|
||||||
space = if commit.space >= parent.space then
|
space = if commit.space >= parent.space then
|
||||||
find_free_parent_space(range, parent.space, -1, commit.space)
|
find_free_parent_space(range, parent.space, -1, commit.space)
|
||||||
|
@ -166,7 +159,7 @@ module Network
|
||||||
range.each do |i|
|
range.each do |i|
|
||||||
if i != range.first &&
|
if i != range.first &&
|
||||||
i != range.last &&
|
i != range.last &&
|
||||||
@commits[reversed_index(i)].spaces.include?(overlap_space) then
|
@commits[i].spaces.include?(overlap_space) then
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
@ -184,7 +177,7 @@ module Network
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
time_range = leaves.last.time..leaves.first.time
|
time_range = leaves.first.time..leaves.last.time
|
||||||
space_base = get_space_base(leaves)
|
space_base = get_space_base(leaves)
|
||||||
space = find_free_space(time_range, 2, space_base)
|
space = find_free_space(time_range, 2, space_base)
|
||||||
leaves.each do |l|
|
leaves.each do |l|
|
||||||
|
@ -198,17 +191,17 @@ module Network
|
||||||
end
|
end
|
||||||
|
|
||||||
# and mark it as reserved
|
# and mark it as reserved
|
||||||
min_time = leaves.last.time
|
if parent_time.nil?
|
||||||
leaves.last.parents(@map).each do |parent|
|
min_time = leaves.first.time
|
||||||
if parent.time < min_time
|
else
|
||||||
min_time = parent.time
|
min_time = parent_time + 1
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if parent_time.nil?
|
max_time = leaves.last.time
|
||||||
max_time = leaves.first.time
|
leaves.last.parents(@map).each do |parent|
|
||||||
else
|
if max_time < parent.time
|
||||||
max_time = parent_time - 1
|
max_time = parent.time
|
||||||
|
end
|
||||||
end
|
end
|
||||||
mark_reserved(min_time..max_time, space)
|
mark_reserved(min_time..max_time, space)
|
||||||
|
|
||||||
|
@ -289,9 +282,5 @@ module Network
|
||||||
end
|
end
|
||||||
refs_cache
|
refs_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
def reversed_index(index)
|
|
||||||
-index - 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,6 +16,7 @@ require 'email_spec'
|
||||||
require 'sidekiq/testing/inline'
|
require 'sidekiq/testing/inline'
|
||||||
require 'capybara/poltergeist'
|
require 'capybara/poltergeist'
|
||||||
Capybara.javascript_driver = :poltergeist
|
Capybara.javascript_driver = :poltergeist
|
||||||
|
Capybara.default_wait_time = 10
|
||||||
|
|
||||||
# Requires supporting ruby files with custom matchers and macros, etc,
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
||||||
# in spec/support/ and its subdirectories.
|
# in spec/support/ and its subdirectories.
|
||||||
|
|
Loading…
Reference in a new issue