summaryrefslogtreecommitdiffstats
path: root/sonar-server/src/main
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2014-07-07 20:32:31 +0600
committerStas Vilchik <vilchiks@gmail.com>2014-07-07 20:32:40 +0600
commit0bf64521daeeaa777fee0c01f2fa4dc17dd85945 (patch)
tree2da4aec27482be10448ac70216d1a08905be6145 /sonar-server/src/main
parent6ace78128277d173c22a02518305838454bd95f8 (diff)
downloadsonarqube-0bf64521daeeaa777fee0c01f2fa4dc17dd85945.tar.gz
sonarqube-0bf64521daeeaa777fee0c01f2fa4dc17dd85945.zip
SONAR-5207 Treemap drilldown
Diffstat (limited to 'sonar-server/src/main')
-rw-r--r--sonar-server/src/main/coffee/widgets/base.coffee7
-rw-r--r--sonar-server/src/main/coffee/widgets/treemap.coffee103
-rw-r--r--sonar-server/src/main/coffee/widgets/word-cloud.coffee6
-rw-r--r--sonar-server/src/main/less/style.less17
4 files changed, 95 insertions, 38 deletions
diff --git a/sonar-server/src/main/coffee/widgets/base.coffee b/sonar-server/src/main/coffee/widgets/base.coffee
index 5531ceb2d92..bf0522bb8b4 100644
--- a/sonar-server/src/main/coffee/widgets/base.coffee
+++ b/sonar-server/src/main/coffee/widgets/base.coffee
@@ -2,8 +2,11 @@ window.SonarWidgets ?= {}
class BaseWidget
lineHeight: 20
- colorLow: '#d62728'
- colorHigh: '#85bb43'
+
+ colors4: ['#ee0000', '#f77700', '#80cc00', '#00aa00']
+ colors4r: ['#00aa00', '#80cc00', '#f77700', '#ee0000']
+ colors5: ['#ee0000', '#f77700', '#ffee00', '#80cc00', '#00aa00']
+ colors5r: ['#00aa00', '#80cc00', '#ffee00', '#f77700', '#ee0000']
colorUnknown: '#777'
diff --git a/sonar-server/src/main/coffee/widgets/treemap.coffee b/sonar-server/src/main/coffee/widgets/treemap.coffee
index bbdb72bb8f3..91ebfa623e1 100644
--- a/sonar-server/src/main/coffee/widgets/treemap.coffee
+++ b/sonar-server/src/main/coffee/widgets/treemap.coffee
@@ -1,5 +1,6 @@
class Treemap extends window.SonarWidgets.BaseWidget
- sizeLow: 10
+ sizeLow: 11
+ sizeMedium: 13
sizeHigh: 24
@@ -15,34 +16,34 @@ class Treemap extends window.SonarWidgets.BaseWidget
renderTreemap: ->
- @treemap = d3.layout.treemap()
- @treemap.value (d) =>
- @sizeMetric.value d
- @cells = @box.selectAll('.treemap-cell').data @getNodes()
+ nodes = @getNodes()
+ @cells = @box.selectAll('.treemap-cell').data nodes
+ @cells.exit().remove()
cellsEnter = @cells.enter().append 'div'
cellsEnter.classed 'treemap-cell', true
- cellsEnter.attr 'title', (d) => @tooltip d
- cellsEnter.style 'color', (d) =>
- if @colorMetric.value(d)? then @color @colorMetric.value(d) else @colorUnknown
- cellsEnter.style 'font-size', (d) => "#{@size @sizeMetric.value d}px"
+ cellsEnter.append('div').classed 'treemap-inner', true
- cellsLink = cellsEnter.append('a').classed 'treemap-dashboard', true
- cellsLink.attr 'href', (d) =>
- url = @options().baseUrl + encodeURIComponent(d.key)
- url += '?metric=' + encodeURIComponent(@colorMetric.key) if d.qualifier == 'CLA' || d.qualifier == 'FIL'
- url
- cellsLink.append('i').attr 'class', (d) -> "icon-qualifier-#{d.qualifier.toLowerCase()}"
+ @cells.attr 'title', (d) => @tooltip d
+ @cells.style 'background-color', (d) =>
+ if @colorMetric.value(d)? then @color @colorMetric.value(d) else @colorUnknown
- @cellsInner = cellsEnter.append('div').classed 'treemap-inner', true
+ @cellsInner = @box.selectAll('.treemap-inner').data nodes
@cellsInner.text (d) -> d.longName
- @cellsInner.style 'border-color', (d) =>
- if @colorMetric.value(d)? then @color @colorMetric.value(d) else @colorUnknown
+
+# cellsLink = cellsEnter.append('a').classed 'treemap-dashboard', true
+# cellsLink.attr 'href', (d) =>
+# url = @options().baseUrl + encodeURIComponent(d.key)
+# url += '?metric=' + encodeURIComponent(@colorMetric.key) if d.qualifier == 'CLA' || d.qualifier == 'FIL'
+# url
+# cellsLink.append('i').attr 'class', (d) -> "icon-qualifier-#{d.qualifier.toLowerCase()}"
@attachEvents cellsEnter
attachEvents: (cells) ->
+ cells.on 'click', (d) =>
+ @requestChildren d.key
positionCells: ->
@@ -50,9 +51,23 @@ class Treemap extends window.SonarWidgets.BaseWidget
@cells.style 'top', (d) -> "#{d.y}px"
@cells.style 'width', (d) -> "#{d.dx}px"
@cells.style 'height', (d) -> "#{d.dy}px"
- @cells.classed 'treemap-cell-small', (d) -> d.dy < 60
- @cells.classed 'treemap-cell-very-small', (d) -> d.dx < 20 || d.dy < 20
- @cellsInner.style 'line-height', (d) -> "#{d.dy}px"
+ @cells.style 'line-height', (d) -> "#{d.dy}px"
+ @cells.style 'font-size', (d) => "#{@size d.dx}px"
+# @cells.classed 'treemap-cell-small', (d) -> d.dy < 60
+# @cells.classed 'treemap-cell-very-small', (d) -> d.dx < 20 || d.dy < 20
+
+
+ renderLegend: (box) ->
+ @legend = box.insert 'div', ':first-child'
+ @legend.classed 'legend', true
+ @legend.classed 'legend-html', true
+ @legend.append('span').classed('legend-text', true).html "Size: <span class='legend-text-main'>#{@sizeMetric.name}</span>"
+ @legend.append('span').classed('legend-text', true).html "Color: <span class='legend-text-main'>#{@colorMetric.name}</span>"
+
+ # Show maxResultsReached message
+ if @maxResultsReached()
+ maxResultsReachedLabel = box.append('div').text @options().maxItemsReachedMessage
+ maxResultsReachedLabel.classed 'max-results-reached-message', true
render: (container) ->
@@ -65,20 +80,17 @@ class Treemap extends window.SonarWidgets.BaseWidget
@addMetric 'sizeMetric', 1
# Configure scales
- @color = d3.scale.linear().domain([0, 100])
+ @color = d3.scale.linear().domain([0, 25, 50, 75, 100])
if @colorMetric.direction == 1
- @color.range [@colorLow, @colorHigh]
+ @color.range @colors5
else
- @color.range [@colorHigh, @colorLow]
-
- sizeDomain = d3.extent @components(), (d) => @sizeMetric.value d
- @size = d3.scale.linear().domain(sizeDomain).range [@sizeLow, @sizeHigh]
+ @color.range @colors5r
+ @size = d3.scale.linear().domain([80, 300]).range([@sizeLow, @sizeHigh]).clamp true
- # Show maxResultsReached message
- if @maxResultsReached()
- maxResultsReachedLabel = box.append('div').text @options().maxItemsReachedMessage
- maxResultsReachedLabel.classed 'max-results-reached-message', true
+ @treemap = d3.layout.treemap()
+ @treemap.value (d) => @sizeMetric.value d
+ @renderLegend box
@renderTreemap()
super
@@ -92,5 +104,34 @@ class Treemap extends window.SonarWidgets.BaseWidget
@positionCells()
+ stopDrilldown: ->
+
+
+
+ requestChildren: (key) ->
+ metrics = @metricsPriority().join ','
+ RESOURCES_URL = "#{baseUrl}/api/resources/index"
+ jQuery.get(RESOURCES_URL, resource: key, depth: 1, metrics: metrics).done (r) =>
+ components = _.filter r, (component) =>
+ hasSizeMetric = => _.findWhere component.msr, key: @sizeMetric.key
+ _.isArray(component.msr) && component.msr.length > 0 && hasSizeMetric()
+
+ if _.isArray(components) && components.length > 0
+ components = components.map (component) =>
+ measures = {}
+ component.msr.forEach (measure) ->
+ measures[measure.key] = val: measure.val, fval: measure.frmt_val
+
+ key: component.key
+ name: component.name
+ longName: component.lname
+ qualifier: component.qualifier
+ measures: measures
+ @components components
+ @renderTreemap()
+ @positionCells()
+ else @stopDrilldown()
+
+
window.SonarWidgets.Treemap = Treemap
diff --git a/sonar-server/src/main/coffee/widgets/word-cloud.coffee b/sonar-server/src/main/coffee/widgets/word-cloud.coffee
index 1d98fd1add0..725ba62775f 100644
--- a/sonar-server/src/main/coffee/widgets/word-cloud.coffee
+++ b/sonar-server/src/main/coffee/widgets/word-cloud.coffee
@@ -40,11 +40,11 @@ class WordCloud extends window.SonarWidgets.BaseWidget
@addMetric 'sizeMetric', 1
# Configure scales
- @color = d3.scale.linear().domain([0, 100])
+ @color = d3.scale.linear().domain([0, 33, 67, 100])
if @colorMetric.direction == 1
- @color.range [@colorLow, @colorHigh]
+ @color.range @colors4
else
- @color.range [@colorHigh, @colorLow]
+ @color.range @colors4r
sizeDomain = d3.extent @components(), (d) => @sizeMetric.value d
@size = d3.scale.linear().domain(sizeDomain).range [@sizeLow, @sizeHigh]
diff --git a/sonar-server/src/main/less/style.less b/sonar-server/src/main/less/style.less
index 1df5fea23bd..325989f1496 100644
--- a/sonar-server/src/main/less/style.less
+++ b/sonar-server/src/main/less/style.less
@@ -2735,6 +2735,14 @@ div.rule-title {
-webkit-transform-origin: center;
}
+.sonar-d3 .legend-html {
+ margin-bottom: 10px;
+ color: @secondFontColor;
+
+ .legend-text + .legend-text { margin-left: 15px; }
+ .legend-text-main { font-weight: 500; }
+}
+
.sonar-d3 .details-color-indicator {
fill: #fff;
transition: fill 0.2s ease;
@@ -2781,8 +2789,11 @@ div.rule-title {
white-space: nowrap;
margin-right: 14px;
text-decoration: none;
+ border-bottom: 1px solid transparent;
- &:hover { text-decoration: underline; }
+ &:hover {
+ border-bottom: 1px solid;
+ }
}
.sonar-d3 .max-results-reached-message {
@@ -2808,6 +2819,7 @@ div.rule-title {
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
.box-sizing(border-box);
+ cursor: pointer;
}
.sonar-d3 .treemap-inner {
@@ -2815,7 +2827,8 @@ div.rule-title {
z-index: 1;
top: 0; left: 0; bottom: 0; right: 0;
padding: 0 5px;
- border: 1px solid;
+ color: #fff;
+ font-weight: 300;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;