diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2014-07-04 17:06:25 +0600 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2014-07-04 17:06:34 +0600 |
commit | bc7dddf031537bc5a658573c63f7bc9d73e633cb (patch) | |
tree | 8345e212e201be908d0fd635103e42e0f72566ae /sonar-server | |
parent | 0b07455499c27bd5d18acf8c5e59ab93ead4d11c (diff) | |
download | sonarqube-bc7dddf031537bc5a658573c63f7bc9d73e633cb.tar.gz sonarqube-bc7dddf031537bc5a658573c63f7bc9d73e633cb.zip |
SONAR-5207 Treemap as a metric widget skeleton
Diffstat (limited to 'sonar-server')
-rw-r--r-- | sonar-server/Gruntfile.coffee | 2 | ||||
-rw-r--r-- | sonar-server/src/main/coffee/widgets/base.coffee | 12 | ||||
-rw-r--r-- | sonar-server/src/main/coffee/widgets/treemap.coffee | 96 | ||||
-rw-r--r-- | sonar-server/src/main/coffee/widgets/word-cloud.coffee | 11 | ||||
-rw-r--r-- | sonar-server/src/main/less/style.less | 42 |
5 files changed, 153 insertions, 10 deletions
diff --git a/sonar-server/Gruntfile.coffee b/sonar-server/Gruntfile.coffee index 0f06e25c577..e49048f7eff 100644 --- a/sonar-server/Gruntfile.coffee +++ b/sonar-server/Gruntfile.coffee @@ -94,6 +94,7 @@ module.exports = (grunt) -> '<%= pkg.assets %>js/widgets/pie-chart.js' '<%= pkg.assets %>js/widgets/histogram.js' '<%= pkg.assets %>js/widgets/word-cloud.js' + '<%= pkg.assets %>js/widgets/treemap.js' '<%= pkg.assets %>js/top-search.js' '<%= pkg.assets %>js/sortable.js' '<%= pkg.assets %>js/common/inputs.js' @@ -125,6 +126,7 @@ module.exports = (grunt) -> '<%= pkg.assets %>js/widgets/pie-chart.js' '<%= pkg.assets %>js/widgets/histogram.js' '<%= pkg.assets %>js/widgets/word-cloud.js' + '<%= pkg.assets %>js/widgets/treemap.js' '<%= pkg.assets %>js/top-search.js' '<%= pkg.assets %>js/sortable.js' '<%= pkg.assets %>js/common/inputs.js' diff --git a/sonar-server/src/main/coffee/widgets/base.coffee b/sonar-server/src/main/coffee/widgets/base.coffee index 133c15e464d..5531ceb2d92 100644 --- a/sonar-server/src/main/coffee/widgets/base.coffee +++ b/sonar-server/src/main/coffee/widgets/base.coffee @@ -2,6 +2,9 @@ window.SonarWidgets ?= {} class BaseWidget lineHeight: 20 + colorLow: '#d62728' + colorHigh: '#85bb43' + colorUnknown: '#777' constructor: -> @@ -47,4 +50,11 @@ class BaseWidget @ -window.SonarWidgets.BaseWidget = BaseWidget
\ No newline at end of file + tooltip: (d) -> + title = d.longName + title += "\n#{@colorMetric.name}: #{@colorMetric.formattedValue d}" if @colorMetric.value(d)? + title += "\n#{@sizeMetric.name}: #{@sizeMetric.formattedValue d}" if @sizeMetric.value(d)? + title + + +window.SonarWidgets.BaseWidget = BaseWidget diff --git a/sonar-server/src/main/coffee/widgets/treemap.coffee b/sonar-server/src/main/coffee/widgets/treemap.coffee new file mode 100644 index 00000000000..7cb065d02b4 --- /dev/null +++ b/sonar-server/src/main/coffee/widgets/treemap.coffee @@ -0,0 +1,96 @@ +class Treemap extends window.SonarWidgets.BaseWidget + sizeLow: 10 + sizeHigh: 24 + + + constructor: -> + @addField 'width', null + @addField 'height', null + @addField 'maxResultsReached', false + super + + + getNodes: -> + @treemap.nodes(children: @components()).filter (d) -> !d.children + + + renderTreemap: -> + @treemap = d3.layout.treemap() + @treemap.value (d) => + @sizeMetric.value d + @cells = @box.selectAll('.treemap-cell').data @getNodes() + + 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" + + cellsLink = cellsEnter.append('a').classed 'treemap-detach', true + cellsLink.attr 'target', '_blank' + 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()}" + + @cellsInner = cellsEnter.append('div').classed 'treemap-inner', true + @cellsInner.text (d) -> d.longName + @cellsInner.style 'border-color', (d) => + if @colorMetric.value(d)? then @color @colorMetric.value(d) else @colorUnknown + + @attachEvents cellsEnter + + + attachEvents: (cells) -> + + + positionCells: -> + @cells.style 'left', (d) -> "#{d.x}px" + @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 + @cellsInner.style 'line-height', (d) -> "#{d.dy}px" + + + render: (container) -> + box = d3.select(container).append('div') + box.classed 'sonar-d3', true + @box = box.append('div').classed 'treemap-container', true + + # Configure metrics + @addMetric 'colorMetric', 0 + @addMetric 'sizeMetric', 1 + + # Configure scales + @color = d3.scale.linear().domain([0, 100]) + if @colorMetric.direction == 1 + @color.range [@colorLow, @colorHigh] + else + @color.range [@colorHigh, @colorLow] + + sizeDomain = d3.extent @components(), (d) => @sizeMetric.value d + @size = d3.scale.linear().domain(sizeDomain).range [@sizeLow, @sizeHigh] + + # Show maxResultsReached message + if @maxResultsReached() + maxResultsReachedLabel = box.append('div').text @options().maxItemsReachedMessage + maxResultsReachedLabel.classed 'max-results-reached-message', true + + @renderTreemap() + super + + + update: -> + @width @box.property 'offsetWidth' + @height (@width() / 100.0 * @options().heightInPercents) + @box.style 'height', "#{@height()}px" + @treemap.size [@width(), @height()] + @cells.data @getNodes() + @positionCells() + + + +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 1e09b55a6d5..1d98fd1add0 100644 --- a/sonar-server/src/main/coffee/widgets/word-cloud.coffee +++ b/sonar-server/src/main/coffee/widgets/word-cloud.coffee @@ -1,7 +1,4 @@ class WordCloud extends window.SonarWidgets.BaseWidget - colorLow: '#d62728' - colorHigh: '#1f77b4' - colorUnknown: '#777' sizeLow: 10 sizeHigh: 24 @@ -22,11 +19,7 @@ class WordCloud extends window.SonarWidgets.BaseWidget url = @options().baseUrl + encodeURIComponent(d.key) url += '?metric=' + encodeURIComponent(@colorMetric.key) if d.qualifier == 'CLA' || d.qualifier == 'FIL' url - wordsEnter.attr 'title', (d) => - title = d.longName - title += " | #{@colorMetric.name}: #{@colorMetric.formattedValue d}" if @colorMetric.value(d)? - title += " | #{@sizeMetric.name}: #{@sizeMetric.formattedValue d}" if @sizeMetric.value(d)? - title + wordsEnter.attr 'title', (d) => @tooltip d words.style 'color', (d) => if @colorMetric.value(d)? then @color @colorMetric.value(d) else @colorUnknown @@ -67,4 +60,4 @@ class WordCloud extends window.SonarWidgets.BaseWidget -window.SonarWidgets.WordCloud = WordCloud
\ No newline at end of file +window.SonarWidgets.WordCloud = WordCloud diff --git a/sonar-server/src/main/less/style.less b/sonar-server/src/main/less/style.less index d359113276f..aedda2cd0e9 100644 --- a/sonar-server/src/main/less/style.less +++ b/sonar-server/src/main/less/style.less @@ -2799,6 +2799,48 @@ div.rule-title { fill: #777; } +.sonar-d3 .treemap-container { + position: relative; +} + +.sonar-d3 .treemap-cell { + position: absolute; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + .box-sizing(border-box); +} + +.sonar-d3 .treemap-inner { + position: absolute; + z-index: 1; + top: 0; left: 0; bottom: 0; right: 0; + padding: 0 5px; + border: 1px solid; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.sonar-d3 .treemap-detach { + position: absolute; + z-index: 2; + top: 5px; right: 5px; + line-height: 16px; + color: inherit; + opacity: 0.5; + + &:hover { opacity: 1; } +} + +.sonar-d3 .treemap-cell-small { + .treemap-inner { text-indent: -9999px; } + .treemap-detach { + top: 50%; left: 50%; + margin: -8px 0 0 -8px; + } +} + /* ------------------- Admin pages ------------------- */ |