From 0bf64521daeeaa777fee0c01f2fa4dc17dd85945 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Mon, 7 Jul 2014 20:32:31 +0600 Subject: [PATCH] SONAR-5207 Treemap drilldown --- .../src/main/coffee/widgets/base.coffee | 7 +- .../src/main/coffee/widgets/treemap.coffee | 103 ++++++++++++------ .../src/main/coffee/widgets/word-cloud.coffee | 6 +- sonar-server/src/main/less/style.less | 17 ++- 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: #{@sizeMetric.name}" + @legend.append('span').classed('legend-text', true).html "Color: #{@colorMetric.name}" + + # 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; -- 2.39.5