summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2014-04-22 18:08:45 +0600
committerStas Vilchik <vilchiks@gmail.com>2014-04-22 18:08:54 +0600
commit1315fe1d47399c821a12d647e4c62b1fd54113fc (patch)
tree610ff11e6de749825ebe93ea6c338bc5b69c36a3
parent617bd05a326531e8d64faa8ba0bf54fbe0bce421 (diff)
downloadsonarqube-1315fe1d47399c821a12d647e4c62b1fd54113fc.tar.gz
sonarqube-1315fe1d47399c821a12d647e4c62b1fd54113fc.zip
Component Viewer: ui improvements
-rw-r--r--sonar-server/src/main/coffee/coding-rules/app.coffee2
-rw-r--r--sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee4
-rw-r--r--sonar-server/src/main/coffee/component-viewer/main.coffee20
-rw-r--r--sonar-server/src/main/coffee/component-viewer/source.coffee44
-rw-r--r--sonar-server/src/main/coffee/component-viewer/workspace.coffee (renamed from sonar-server/src/main/coffee/component-viewer/header.coffee)12
-rw-r--r--sonar-server/src/main/coffee/quality-gate/layout.coffee2
-rw-r--r--sonar-server/src/main/coffee/quality-gate/router.coffee2
-rw-r--r--sonar-server/src/main/hbs/component-viewer/coveragePopup.hbs4
-rw-r--r--sonar-server/src/main/hbs/component-viewer/header.hbs26
-rw-r--r--sonar-server/src/main/hbs/component-viewer/layout.hbs2
-rw-r--r--sonar-server/src/main/hbs/component-viewer/source.hbs73
-rw-r--r--sonar-server/src/main/hbs/component-viewer/workspace.hbs12
-rw-r--r--sonar-server/src/main/js/issues/app.js4
-rw-r--r--sonar-server/src/main/less/component-viewer.less152
-rw-r--r--sonar-server/src/main/less/ui.less9
15 files changed, 244 insertions, 124 deletions
diff --git a/sonar-server/src/main/coffee/coding-rules/app.coffee b/sonar-server/src/main/coffee/coding-rules/app.coffee
index 9d1393c46b2..149e9f44838 100644
--- a/sonar-server/src/main/coffee/coding-rules/app.coffee
+++ b/sonar-server/src/main/coffee/coding-rules/app.coffee
@@ -180,7 +180,7 @@ requirejs [
# Construct header
App.addInitializer ->
@codingRulesHeaderView = new CodingRulesHeaderView app: @
- @layout.headerRegion.show @codingRulesHeaderView
+ @layout.workspaceRegion.show @codingRulesHeaderView
# Define coding rules
diff --git a/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee b/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee
index c225a07b428..cc5ba87677c 100644
--- a/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee
+++ b/sonar-server/src/main/coffee/component-viewer/coverage-popup.coffee
@@ -20,9 +20,7 @@ define [
onRender: ->
@$el.detach().appendTo $('body')
- @$el.css
- top: @options.triggerEl.offset().top
- left: @options.triggerEl.offset().left + @options.triggerEl.outerWidth()
+ @$el.css 'top', @options.triggerEl.offset().top
$('body').on 'click.coverage-popup', =>
$('body').off 'click.coverage-popup'
diff --git a/sonar-server/src/main/coffee/component-viewer/main.coffee b/sonar-server/src/main/coffee/component-viewer/main.coffee
index c207d8c3f87..2471f3fa1ea 100644
--- a/sonar-server/src/main/coffee/component-viewer/main.coffee
+++ b/sonar-server/src/main/coffee/component-viewer/main.coffee
@@ -2,13 +2,13 @@ define [
'backbone'
'backbone.marionette'
'templates/component-viewer'
- 'component-viewer/header'
+ 'component-viewer/workspace'
'component-viewer/source'
], (
Backbone
Marionette
Templates
- HeaderView
+ WorkspaceView
SourceView
) ->
@@ -24,25 +24,27 @@ define [
regions:
- headerRegion: '.component-viewer-header'
+ workspaceRegion: '.component-viewer-workspace'
sourceRegion: '.component-viewer-source'
initialize: ->
@workspace = new Backbone.Collection()
@component = new Backbone.Model()
- @headerView = new HeaderView
- model: @component
+ @workspaceView = new WorkspaceView
+ collection: @workspace
main: @
@source = new Backbone.Model()
- @sourceView = new SourceView model: @source, main: @
+ @sourceView = new SourceView
+ model: @source
+ main: @
@settings = new Backbone.Model issues: false, coverage: true, duplications: false
onRender: ->
- @headerRegion.show @headerView
+ @workspaceRegion.show @workspaceView
@sourceRegion.show @sourceView
@@ -92,6 +94,7 @@ define [
showCoverage: ->
+ @settings.set 'coverage', true
unless @source.has 'coverage'
metrics = 'coverage_line_hits_data,covered_conditions_by_line,conditions_by_line'
@requestComponent(@key, metrics).done (data) =>
@@ -102,7 +105,8 @@ define [
hideCoverage: ->
- @sourceView.hideCoverage()
+ @settings.set 'coverage', false
+ @sourceView.render()
addTransition: (key, transition) ->
diff --git a/sonar-server/src/main/coffee/component-viewer/source.coffee b/sonar-server/src/main/coffee/component-viewer/source.coffee
index e4ea8c7502a..27f72f9da40 100644
--- a/sonar-server/src/main/coffee/component-viewer/source.coffee
+++ b/sonar-server/src/main/coffee/component-viewer/source.coffee
@@ -17,42 +17,61 @@ define [
events:
- 'click .coverage a': 'showCoveragePopup'
+ 'click .settings-toggle button': 'toggleSettings'
+ 'change #source-coverage': 'toggleCoverage'
+ 'click .coverage-tests': 'showCoveragePopup'
onRender: ->
@delegateEvents()
+ @showSettings = false
showSpinner: ->
@$el.html '<div style="padding: 10px;"><i class="spinner"></i></div>'
- hideCoverage: ->
- @$('.coverage').hide()
+
+ toggleSettings: ->
+ @$('.settings-toggle button').toggleClass 'open'
+ @$('.component-viewer-source-settings').toggleClass 'open'
+
+
+ toggleCoverage: (e) ->
+ active = $(e.currentTarget).is ':checked'
+ @showSettings = true
+ if active then @options.main.showCoverage() else @options.main.hideCoverage()
showCoveragePopup: (e) ->
e.stopPropagation()
$('body').click()
popup = new CoveragePopupView
- triggerEl: $(e.currentTarget).closest('td')
+ triggerEl: $(e.currentTarget)
main: @options.main
popup.render()
- serializeData: ->
+ prepareSource: ->
source = @model.get 'source'
coverage = @model.get 'coverage'
coverageConditions = @model.get 'coverageConditions'
conditions = @model.get 'conditions'
- source = _.map source, (code, line) ->
+ _.map source, (code, line) ->
lineCoverage = coverage? && coverage[line]? && coverage[line]
+ lineCoverage = +lineCoverage if _.isString lineCoverage
lineCoverageConditions = coverageConditions? && coverageConditions[line]? && coverageConditions[line]
+ lineCoverageConditions = +lineCoverageConditions if _.isString lineCoverageConditions
lineConditions = conditions? && conditions[line]? && conditions[line]
- lineCoverageStatus = lineCoverage? && if lineCoverage > 0 then 'green' else 'red'
+ lineConditions = +lineConditions if _.isString lineConditions
+
+ lineCoverageStatus = null
+ if _.isNumber lineCoverage
+ lineCoverageStatus = 'red' if lineCoverage == 0
+ lineCoverageStatus = 'green' if lineCoverage > 0
+
lineCoverageConditionsStatus = null
- if lineCoverageConditions? && conditions?
+ if _.isNumber(lineCoverageConditions) && _.isNumber(conditions)
lineCoverageConditionsStatus = 'red' if lineCoverageConditions == 0
lineCoverageConditionsStatus = 'orange' if lineCoverageConditions > 0 && lineCoverageConditions < lineConditions
lineCoverageConditionsStatus = 'green' if lineCoverageConditions == lineConditions
@@ -63,5 +82,10 @@ define [
coverageStatus: lineCoverageStatus
coverageConditions: lineCoverageConditions
conditions: lineConditions
- coverageConditionsStatus: lineCoverageConditionsStatus
- source: source \ No newline at end of file
+ coverageConditionsStatus: lineCoverageConditionsStatus || lineCoverageStatus
+
+
+ serializeData: ->
+ source: @prepareSource()
+ settings: @options.main.settings.toJSON()
+ showSettings: @showSettings \ No newline at end of file
diff --git a/sonar-server/src/main/coffee/component-viewer/header.coffee b/sonar-server/src/main/coffee/component-viewer/workspace.coffee
index e64f546d43e..4eaf851fa72 100644
--- a/sonar-server/src/main/coffee/component-viewer/header.coffee
+++ b/sonar-server/src/main/coffee/component-viewer/workspace.coffee
@@ -9,13 +9,12 @@ define [
$ = jQuery
- class HeaderView extends Marionette.ItemView
- template: Templates['header']
+ class WorkspaceView extends Marionette.ItemView
+ template: Templates['workspace']
events:
'click .component-viewer-workspace-item [data-key]': 'goToWorkspaceItem'
- 'click [data-option=coverage]': 'toggleCoverage'
onRender: ->
@@ -31,13 +30,6 @@ define [
@options.main.addTransition workspaceItem.get('key'), workspaceItem.get('transition')
- toggleCoverage: (e) ->
- el = $(e.currentTarget)
- active = el.is '.active'
- el.toggleClass 'active'
- if active then @options.main.hideCoverage() else @options.main.showCoverage()
-
-
serializeData: ->
_.extend super,
workspace: @options.main.workspace.toJSON()
diff --git a/sonar-server/src/main/coffee/quality-gate/layout.coffee b/sonar-server/src/main/coffee/quality-gate/layout.coffee
index 0b5941655d5..0edc32c223e 100644
--- a/sonar-server/src/main/coffee/quality-gate/layout.coffee
+++ b/sonar-server/src/main/coffee/quality-gate/layout.coffee
@@ -25,7 +25,7 @@ define [
updateLayout: ->
empty = @options.app.qualityGates.length == 0
- @$(@headerRegion.el).toggle !empty
+ @$(@workspaceRegion.el).toggle !empty
@$(@detailsRegion.el).toggle !empty
diff --git a/sonar-server/src/main/coffee/quality-gate/router.coffee b/sonar-server/src/main/coffee/quality-gate/router.coffee
index f21161a97bf..834da1bf9ca 100644
--- a/sonar-server/src/main/coffee/quality-gate/router.coffee
+++ b/sonar-server/src/main/coffee/quality-gate/router.coffee
@@ -28,7 +28,7 @@ define [
qualityGateDetailHeaderView = new QualityGateDetailHeaderView
app: @app
model: qualityGate
- @app.layout.headerRegion.show qualityGateDetailHeaderView
+ @app.layout.workspaceRegion.show qualityGateDetailHeaderView
qualityGateDetailView = new QualityGateDetailView
app: @app
diff --git a/sonar-server/src/main/hbs/component-viewer/coveragePopup.hbs b/sonar-server/src/main/hbs/component-viewer/coveragePopup.hbs
index 1e8d81aa27d..d11d2221090 100644
--- a/sonar-server/src/main/hbs/component-viewer/coveragePopup.hbs
+++ b/sonar-server/src/main/hbs/component-viewer/coveragePopup.hbs
@@ -1,7 +1,7 @@
<div class="component-viewer-popup-section">
<a data-key="org.codehaus.sonar:sonar-plugin-api:src/test/java/org/sonar/api/resources/ResourceTypeTreeTest.java"
class="component-viewer-popup-section-title">
- src/test/java/org/sonar/api/resources/ResourceTypeTreeTest.java
+ ResourceTypeTreeTest.java
</a>
<ul class="component-viewer-popup-list">
<li><i class="icon-alert-ok"></i> 216ms forbidDuplicatedType</li>
@@ -12,7 +12,7 @@
<div class="component-viewer-popup-section">
<a data-key="org.codehaus.sonar:sonar-plugin-api:src/test/java/org/sonar/api/resources/ResourceTypesTest.java"
class="component-viewer-popup-section-title">
- src/test/java/org/sonar/api/resources/ResourceTypesTest.java
+ ResourceTypesTest.java
</a>
<ul class="component-viewer-popup-list">
<li><i class="icon-alert-ok"></i> 115ms fail_on_duplicated_qualifier</li>
diff --git a/sonar-server/src/main/hbs/component-viewer/header.hbs b/sonar-server/src/main/hbs/component-viewer/header.hbs
deleted file mode 100644
index 0e05fdf6a2b..00000000000
--- a/sonar-server/src/main/hbs/component-viewer/header.hbs
+++ /dev/null
@@ -1,26 +0,0 @@
-<div class="component-viewer-workspace">
- <ul class="component-viewer-workspace-list">
- {{#each workspace}}
- <li class="component-viewer-workspace-item">
- {{#if transition}}
- <span class="component-viewer-workspace-transition">
- <i class="icon-move-right"></i>
- </span>
- {{/if}}
- <a data-key="{{key}}">{{qualifierIcon component.qualifier}} {{component.name}}</a>
- </li>
- {{/each}}
- </ul>
-</div>
-
-<div class="component-viewer-options button-group">
- <button data-option="issues" {{#if settings.issues}}class="active"{{/if}}>
- <i class="icon-issue"></i>&nbsp;&nbsp;Issues
- </button>
- <button data-option="coverage" {{#if settings.coverage}}class="active"{{/if}}>
- <i class="icon-coverage"></i>&nbsp;&nbsp;Coverage
- </button>
- <button data-option="duplications" {{#if settings.duplications}}class="active"{{/if}}>
- <i class="icon-duplications"></i>&nbsp;&nbsp;Duplications
- </button>
-</div> \ No newline at end of file
diff --git a/sonar-server/src/main/hbs/component-viewer/layout.hbs b/sonar-server/src/main/hbs/component-viewer/layout.hbs
index 78b06dad147..853611d0a30 100644
--- a/sonar-server/src/main/hbs/component-viewer/layout.hbs
+++ b/sonar-server/src/main/hbs/component-viewer/layout.hbs
@@ -1,2 +1,2 @@
-<div class="component-viewer-header"></div>
+<div class="component-viewer-workspace"></div>
<div class="component-viewer-source"></div> \ No newline at end of file
diff --git a/sonar-server/src/main/hbs/component-viewer/source.hbs b/sonar-server/src/main/hbs/component-viewer/source.hbs
index 5692d126f2a..151109a45b4 100644
--- a/sonar-server/src/main/hbs/component-viewer/source.hbs
+++ b/sonar-server/src/main/hbs/component-viewer/source.hbs
@@ -1,20 +1,59 @@
<table class="sources2 code" cellpadding="0" cellspacing="0">
- {{#each source}}
- <tr class="row">
- <td class="coverage {{#if coverage}}coverage-{{coverageStatus}}{{/if}}">
- {{#if coverage}}<a title="Line is covered by {{coverage}} tests">{{coverage}}</a>{{/if}}
- </td>
- <td class="coverage {{#if coverageConditions}}coverage-{{coverageConditionsStatus}}{{/if}}">
- {{#if coverageConditions}}
- {{#if conditions}}
- <span title="{{coverageConditions}} branches are covered by tests">
- {{coverageConditions}}/{{conditions}}
- </span>
+ <thead>
+ <tr>
+ {{#if settings.coverage}}
+ <th class="stat"></th>
+ <th class="stat"></th>
+ {{/if}}
+ <th class="stat settings-toggle">
+ <button class="button-clean">
+ <i class="icon-settings"></i></i>
+ </button>
+ </th>
+ <th class="stat settings">
+ <ul class="component-viewer-source-settings {{#if showSettings}}open{{/if}}">
+ <li>
+ <input id="source-issues" type="checkbox" {{#if settings.issues}}checked{{/if}}>
+ <label for="source-issues">Issues</label>
+ </li>
+ <li>
+ <input id="source-coverage" type="checkbox" {{#if settings.coverage}}checked{{/if}}>
+ <label for="source-coverage">Coverage</label>
+ </li>
+ <li>
+ <input id="source-duplications" type="checkbox" {{#if settings.duplications}}checked{{/if}}>
+ <label for="source-duplications">Duplications</label>
+ </li>
+ </ul>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#each source}}
+ <tr class="row {{#if ../settings.coverage}}{{#if coverageStatus}}coverage-{{coverageStatus}}{{/if}}{{/if}}">
+
+ {{#if ../settings.coverage}}
+ <td class="stat coverage-tests">
+ {{#if coverage}}
+ <span title="Line is covered by {{coverage}} tests">{{coverage}}</span>
{{/if}}
- {{/if}}
- </td>
- <td class="lid">{{lineNumber}}</td>
- <td class="line"><pre>{{{code}}}</pre></td>
- </tr>
- {{/each}}
+ </td>
+
+ <td class="stat coverage-conditions">
+ {{#if coverageConditions}}
+ {{#if conditions}}
+ <span title="{{coverageConditions}} branches are covered by tests">
+ {{coverageConditions}}/{{conditions}}
+ </span>
+ {{/if}}
+ {{/if}}
+ </td>
+ {{/if}}
+
+ <td class="stat lid">{{lineNumber}}</td>
+
+ <td class="line"><pre>{{{code}}}</pre></td>
+ </tr>
+ {{/each}}
+ </tbody>
</table> \ No newline at end of file
diff --git a/sonar-server/src/main/hbs/component-viewer/workspace.hbs b/sonar-server/src/main/hbs/component-viewer/workspace.hbs
new file mode 100644
index 00000000000..f25d693d3ac
--- /dev/null
+++ b/sonar-server/src/main/hbs/component-viewer/workspace.hbs
@@ -0,0 +1,12 @@
+<ul class="component-viewer-workspace-list">
+ {{#each workspace}}
+ <li class="component-viewer-workspace-item">
+ {{#if transition}}
+ <span>
+ <i class="icon-move-right"></i>
+ </span>
+ {{/if}}
+ <a data-key="{{key}}">{{qualifierIcon component.qualifier}} {{component.name}}</a>
+ </li>
+ {{/each}}
+</ul> \ No newline at end of file
diff --git a/sonar-server/src/main/js/issues/app.js b/sonar-server/src/main/js/issues/app.js
index 24bcceea5ad..86dc3f5794c 100644
--- a/sonar-server/src/main/js/issues/app.js
+++ b/sonar-server/src/main/js/issues/app.js
@@ -53,7 +53,7 @@ requirejs(
NavigatorApp.addRegions({
- headerRegion: '.navigator-header',
+ workspaceRegion: '.navigator-header',
filtersRegion: '.navigator-filters',
resultsRegion: '.navigator-results',
actionsRegion: '.navigator-actions',
@@ -85,7 +85,7 @@ requirejs(
app: this,
model: this.favoriteFilter
});
- this.headerRegion.show(this.issuesHeaderView);
+ this.workspaceRegion.show(this.issuesHeaderView);
this.issuesView = new Extra.IssuesView({
app: this,
diff --git a/sonar-server/src/main/less/component-viewer.less b/sonar-server/src/main/less/component-viewer.less
index f8b175635ee..03adee5ec97 100644
--- a/sonar-server/src/main/less/component-viewer.less
+++ b/sonar-server/src/main/less/component-viewer.less
@@ -1,6 +1,8 @@
@import "variables";
@import "mixins";
+@workspaceWidth: 260px;
+
.component-viewer {
width: 100%;
@@ -10,41 +12,69 @@
}
-.component-viewer-header {
- position: relative;
- height: 40px;
- padding: 0 10px;
- border-bottom: 1px solid @barBorderColor;
- background-color: @barBackgroundColor;
-}
-
-
.component-viewer-workspace {
- height: 40px;
- line-height: 40px;
- font-size: 0;
+ float: left;
+ width: @workspaceWidth;
+ .box-sizing(border-box);
}
.component-viewer-workspace-item {
- display: inline-block;
- vertical-align: middle;
- font-size: @baseFontSize;
+ height: 30px;
+ line-height: 30px;
+ padding: 0 10px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
- &:last-child { font-weight: bold; }
-}
+ &:first-child {
+ border-bottom: 1px solid @barBorderColor;
+ }
-.component-viewer-workspace-transition {
- padding: 0 10px;
+ &:last-child {
+ font-weight: bold;
+ }
}
+.component-viewer-workspace-transition {
-.component-viewer-options {
- position: absolute;
- top: 8px; right: 10px;
}
.component-viewer-source {
+ border-left: @workspaceWidth solid @barBackgroundColor;
+
+ .sources2 {
+ border-left: 1px solid @barBorderColor;
+ }
+
+ .sources2 th {
+ height: 30px;
+ .box-sizing(border-box);
+
+ &.stat {
+ padding-top: 4px;
+ padding-bottom: 4px;
+ border-left: none;
+ border-right: none;
+ border-bottom: 1px solid @barBorderColor;
+ }
+
+ &.lid {
+ border-right: 1px solid @barBorderColor;
+ }
+
+ &.settings {
+ text-align: left;
+ }
+
+ &.settings-toggle {
+ border-right: 1px solid @barBorderColor;
+ text-align: center;
+ white-space: nowrap;
+
+ .icon-settings { font-size: @iconSmallFontSize; }
+ }
+ }
.sources2 td.line {
padding: 1px 5px;
@@ -56,45 +86,83 @@
}
}
- .sources2 td.lid {
+ .sources2 .stat {
+ min-width: 12px;
padding: 1px 5px;
- border-color: @barBorderColor;
+ border-left: 1px solid @barBorderColor;
+ border-right: 1px solid @barBorderColor;
background-color: @barBackgroundColor;
color: #888;
font-size: 11px;
+ text-align: right;
+ cursor: default;
}
- .sources2 td.coverage {
- padding: 1px 5px;
- background-color: @barBackgroundColor;
- color: #fff;
-
- &.coverage-green { background-color: @green;}
- &.coverage-red { background-color: @red; }
- &.coverage-orange { background-color: @orange; }
+ .sources2 .lid {
+ min-width: 18px;
+ padding-right: 10px;
+ }
- a { color: #fff; }
+ .sources2 .coverage-tests {
+ cursor: pointer;
}
- .sources2 .row:hover {
- td.lid { background-color: darken(@barBackgroundColor, 5%); }
- td.line { background-color: @barBackgroundColor; }
- td.coverage { background-color: darken(@barBackgroundColor, 5%); }
- td.coverage.coverage-green { background-color: darken(@green, 5%); }
- td.coverage.coverage-red { background-color: darken(@red, 5%); }
- td.coverage.coverage-orange { background-color: darken(@orange, 5%); }
+ .sources2 .row {
+
+ &.coverage-green td.stat {
+ background-color: lighten(@green, 15%);
+ border-color: lighten(@green, 7%);
+ color: @baseFontColor;
+
+ &.lid { border-right-color: lighten(@green, 15%); }
+ }
+
+ &.coverage-red td.stat {
+ background-color: lighten(@red, 15%);
+ border-color: lighten(@red, 10%);
+ color: @baseFontColor;
+
+ &.lid { border-right-color: lighten(@red, 15%); }
+ }
+
+ &:hover {
+ td.line { background-color: @barBackgroundColor; }
+
+ td.stat {
+ background-color: darken(@barBackgroundColor, 3%);
+ color: @baseFontColor;
+ }
+
+ &.coverage-green td.stat { background-color: lighten(@green, 10%); }
+ &.coverage-red td.stat { background-color: lighten(@red, 10%); }
+ }
}
}
+.component-viewer-source-settings {
+ visibility: hidden;
+
+ &.open { visibility: visible; }
+
+ & > li {
+ display: inline;
+ margin-right: 10px;
+ }
+}
+
+
.component-viewer-popup {
position: absolute;
z-index: 100;
+ left: 0;
+ width: @workspaceWidth;
padding: 10px;
- border: 1px solid @barBorderColor;
+ border-top: 1px solid @barBorderColor;
+ border-bottom: 1px solid @barBorderColor;
+ .box-sizing(border-box);
background-color: @white;
- box-shadow: @defaultShadow;
}
.component-viewer-popup-section + .component-viewer-popup-section {
diff --git a/sonar-server/src/main/less/ui.less b/sonar-server/src/main/less/ui.less
index 9d904c6aeaa..b688616dc5b 100644
--- a/sonar-server/src/main/less/ui.less
+++ b/sonar-server/src/main/less/ui.less
@@ -95,6 +95,15 @@ input[type=button] {
}
}
+.button-clean,
+.button-clean:hover,
+.button-clean:focus {
+ padding: 0;
+ border: none;
+ background: transparent;
+ color: @baseFontColor;
+}
+
.button-group {
display: inline-block;
vertical-align: middle;