--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/component-viewer'
+ 'common/handlebars-extensions'
+], (
+ Marionette
+ Templates
+) ->
+
+ $ = jQuery
+
+
+ class HeaderView extends Marionette.ItemView
+ template: Templates['header']
+
+
+ ui:
+ expandLinks: '.component-viewer-header-measures-expand'
+ expandedBars: '.component-viewer-header-expanded-bar'
+
+
+ events:
+ 'click @ui.expandLinks': 'showExpandedBar'
+
+
+ onRender: ->
+ @delegateEvents()
+
+
+ showExpandedBar: (e) ->
+ el = $(e.currentTarget)
+ if el.is '.active'
+ @ui.expandLinks.removeClass 'active'
+ @ui.expandedBars.hide()
+ else
+ @ui.expandLinks.removeClass 'active'
+ el.addClass 'active'
+ scope = el.data 'scope'
+ @ui.expandedBars.hide()
+ if scope
+ @ui.expandedBars.filter("[data-scope=#{scope}]").show()
+
+
+ serializeData: ->
+ component = @options.main.component.toJSON()
+ if component.measures
+ component.measures.max_issues = Math.max(
+ component.measures.blocker_issues
+ component.measures.critical_issues
+ component.measures.major_issues
+ component.measures.minor_issues
+ component.measures.info_issues
+ )
+
+ settings: @options.main.settings.toJSON()
+ showSettings: @showSettings
+ component: component
\ No newline at end of file
'templates/component-viewer'
'component-viewer/workspace'
'component-viewer/source'
+ 'component-viewer/header'
+
+ 'component-viewer/mockjax'
], (
Backbone
Marionette
Templates
WorkspaceView
SourceView
+ HeaderView
) ->
$ = jQuery
+ API_COMPONENT = "#{baseUrl}/api/sources/app"
API_SOURCES = "#{baseUrl}/api/sources/show"
- API_RESOURCES = "#{baseUrl}/api/resources"
-
- SOURCE_METRIC_LIST = 'lines,ncloc,functions,accessors,classes,statements,complexity,function_complexity,' +
- 'comment_lines_density,comment_lines,public_documented_api_density,public_undocumented_api,' +
- 'public_api'
-
- COVERAGE_METRIC_LIST = 'coverage,line_coverage,branch_coverage,' +
- 'coverage_line_hits_data,covered_conditions_by_line,conditions_by_line'
-
- ISSUES_METRIC_LIST = 'violations,sqale_index,blocker_violations,critical_violations,major_violations,minor_violations,info_violations'
-
- DUPLICATIONS_METRIC_LIST = 'duplicated_lines_density,duplicated_blocks,duplicated_files,duplicated_lines'
+ API_SCM = "#{baseUrl}/api/sources/scm"
regions:
workspaceRegion: '.component-viewer-workspace'
+ headerRegion: '.component-viewer-header'
sourceRegion: '.component-viewer-source'
model: @source
main: @
+ @headerView = new HeaderView
+ model: @source
+ main: @
+
@settings = new Backbone.Model
issues: false
coverage: false
else
@$el.removeClass 'component-viewer-workspace-enabled'
@sourceRegion.show @sourceView
+ @headerRegion.show @headerView
requestComponent: (key) ->
- metricList = [SOURCE_METRIC_LIST, COVERAGE_METRIC_LIST, ISSUES_METRIC_LIST, DUPLICATIONS_METRIC_LIST].join ','
- $.get API_RESOURCES, resource: key, metrics: metricList, (data) =>
- @component.set data[0]
- @component.set 'measures', _.indexBy(data[0].msr, 'key')
+ $.get API_COMPONENT, key: key, (data) =>
+ @component.set data
requestSource: (key) ->
@source.set source: data.sources
- extractCoverage: (data) ->
- toObj = (d) ->
- q = {}
- d?.split(';').forEach (item) ->
- tokens = item.split '='
- q[tokens[0]] = tokens[1]
- q
-
- msr = data[0].msr
- coverage = toObj _.findWhere(msr, key: 'coverage_line_hits_data')?.data
- coverageConditions = toObj _.findWhere(msr, key: 'covered_conditions_by_line')?.data
- conditions = toObj _.findWhere(msr, key: 'conditions_by_line')?.data
- @source.set
- coverage: coverage
- coverageConditions: coverageConditions
- conditions: conditions
- coverageMeasures = _.reject data[0].msr, (m) ->
- m.key == 'coverage_line_hits_data' || m.key == 'covered_conditions_by_line' || m.key == 'conditions_by_line'
- @component.set 'coverageMeasures', coverageMeasures
-
-
- extractDuplications: (data) ->
- @source.set
- duplications: [
- { from: 18, count: 33 }
- { from: 24, count: 23 }
- { from: 62, count: 33 }
- ]
- duplicationsMeasures = _.sortBy data[0].msr, (item) -> -(item.key == 'duplicated_lines_density')
- @component.set 'duplicationsMeasures', duplicationsMeasures
+ requestSCM: (key) ->
+ $.get API_SCM, key: key, (data) =>
+ @source.set scm: data.scm
extractIssues: (data) ->
@key = key
@sourceView.showSpinner()
source = @requestSource key
- component = @requestComponent key, SOURCE_METRIC_LIST
+ component = @requestComponent key
$.when(source, component).done =>
@workspace.where(key: key).forEach (model) =>
model.set 'component': @component.toJSON()
if @settings.get('issues') then @showIssues() else @hideIssues()
if @settings.get('coverage') then @showCoverage() else @hideCoverage()
if @settings.get('duplications') then @showDuplications() else @hideDuplications()
+ if @settings.get('scm') then @showSCM() else @hideSCM()
showCoverage: ->
@settings.set 'coverage', true
- unless @source.has 'coverage'
- @requestComponent(@key).done (data) =>
- @extractCoverage data
- @sourceView.render()
- else
- @sourceView.render()
+ @render()
hideCoverage: ->
@settings.set 'coverage', false
- @sourceView.render()
+ @render()
showWorkspace: ->
showIssues: (issues) ->
@settings.set 'issues', true
-
- unless @source.has 'issues'
- @requestComponent(@key).done (data) =>
- @extractIssues data
- @sourceView.render()
-
if _.isArray(issues) && issues.length > 0
@source.set 'issues', issues
- @sourceView.render()
+ @render()
hideIssues: ->
@settings.set 'issues', false
- @sourceView.render()
+ @render()
showDuplications: ->
@settings.set 'duplications', true
- unless @source.has 'duplications'
- @requestComponent(@key).done (data) =>
- @extractDuplications data
- @sourceView.render()
- else
- @sourceView.render()
+ @render()
hideDuplications: ->
@settings.set 'duplications', false
- @sourceView.render()
+ @render()
+
+
+ showSCM: ->
+ @settings.set 'scm', true
+ unless @source.has 'duplications'
+ @requestSCM(@key).done => @sourceView.render()
+ else
+ @render()
+
+
+ hideSCM: ->
+ @settings.set 'scm', false
+ @render()
addTransition: (key, transition, optionsForCurrent, options) ->
--- /dev/null
+define ['third-party/jquery.mockjax'], ->
+
+ jQuery.mockjaxSettings.contentType = 'text/json';
+ jQuery.mockjaxSettings.responseTime = 250;
+
+ jQuery.mockjax
+ url: "#{baseUrl}/api/sources/app"
+ responseText: JSON.stringify
+ key: 'org.codehaus.sonar:sonar-dev-maven-plugin:src/main/java/org/sonar/dev/UploadMojo.java'
+ path: 'src/main/java/org/sonar/dev/UploadMojo.java'
+ name: 'UploadMojo.java'
+ q: 'FIL'
+ fav: false
+ project: 'org.codehaus.sonar:sonar-dev-maven-plugin'
+ projectName: 'SonarQube Development Maven Plugin'
+ periods: []
+ measures:
+ 'ncloc': 69
+ 'coverage': '30%'
+ 'duplication_density': '7.4%'
+ 'debt': '3d 2h'
+ 'issues': 4
+ 'blocker_issues': 1
+ 'critical_issues': 2
+ 'major_issues': 0
+ 'minor_issues': 1
+ 'info_issues': 0
\ No newline at end of file
duplications: lineDuplications
+ augmentWithSCM: (source) ->
+ scm = @model.get('scm') || []
+ scm.forEach (s) ->
+ line = source[s[0]]
+ line.scm = author: s[1], date: s[2]
+ source
+
+
augmentWithShow: (sourceLine) ->
show = false
line = sourceLine.lineNumber
prepareSource: ->
source = @model.get 'source'
- _.map source, (item) =>
+ source = _.map source, (item) =>
line = item[0]
base = lineNumber: line, code: item[1]
if @options.main.settings.get('coverage')
if @options.main.settings.get('duplications')
_.extend base, @getLineDuplications(line)
@augmentWithShow base
+ if @options.main.settings.get('scm')
+ source = @augmentWithSCM source
+ source
+
+ getStatColumnsCount: ->
+ count = 1 # line number
+ count += 2 if @options.main.settings.get 'coverage'
+ count += 1 if @options.main.settings.get 'duplications'
+ count += 1 if @options.main.settings.get 'issues'
+ count
serializeData: ->
source: @prepareSource()
settings: @options.main.settings.toJSON()
showSettings: @showSettings
- component: @options.main.component.toJSON()
\ No newline at end of file
+ component: @options.main.component.toJSON()
+ columns: @getStatColumnsCount() + 1
\ No newline at end of file
{{#if settings.duplications}}
<td class="stat"></td>
{{/if}}
+ {{#if settings.scm}}
+ <td class="stat"></td>
+ {{/if}}
<td class="stat lid">
<button class="button-clean js-expand" data-from="{{from}}" data-to="{{to}}"><i class="icon-expand"></i></button>
</td>
--- /dev/null
+<div class="component-viewer-header-bar">
+
+ <div class="component-viewer-header-component">
+ {{#if component.projectName}}
+ <div class="component-viewer-header-component-project">
+ {{qualifierIcon 'TRK'}} {{component.projectName}}
+ </div>
+ {{/if}}
+
+ <div class="component-viewer-header-component-name">
+ {{qualifierIcon component.q}} {{component.path}}
+ </div>
+ </div>
+
+ <div class="component-viewer-header-links">
+ <a><i class="icon-detach"></i></a>
+ <a><i class="icon-link"></i></a>
+ </div>
+
+ <div class="component-viewer-header-measures">
+ <a data-scope="basic" class="component-viewer-header-measures-expand">
+ {{#if component.measures.ncloc}}
+ <div class="component-viewer-header-measure">
+ <span class="component-viewer-header-measure-value">{{component.measures.ncloc}}</span>
+ <span class="component-viewer-header-measure-label">{{t 'metric.ncloc.name'}}</span>
+ </div>
+ {{/if}}
+ <i class="icon-dropdown"></i>
+ </a>
+
+ <a data-scope="issues" class="component-viewer-header-measures-expand">
+ {{#if component.measures.debt}}
+ <div class="component-viewer-header-measure">
+ <span class="component-viewer-header-measure-value">{{component.measures.debt}}</span>
+ <span class="component-viewer-header-measure-label">Debt</span>
+ </div>
+ {{/if}}
+ {{#if component.measures.issues}}
+ <div class="component-viewer-header-measure">
+ <span class="component-viewer-header-measure-value">{{component.measures.issues}}</span>
+ <span class="component-viewer-header-measure-label">{{t 'metric.violations.name'}}</span>
+ </div>
+ {{/if}}
+ <div class="component-viewer-header-measure">
+ <div class="component-viewer-header-measure-issues">
+ <div class="component-viewer-header-measure-issue s-blocker"
+ style="width: {{percent component.measures.blocker_issues component.measures.max_issues}}%;"></div>
+ <div class="component-viewer-header-measure-issue s-critical"
+ style="width: {{percent component.measures.critical_issues component.measures.max_issues}}%;"></div>
+ <div class="component-viewer-header-measure-issue s-major"
+ style="width: {{percent component.measures.major_issues component.measures.max_issues}}%;"></div>
+ <div class="component-viewer-header-measure-issue s-minor"
+ style="width: {{percent component.measures.minor_issues component.measures.max_issues}}%;"></div>
+ <div class="component-viewer-header-measure-issue s-info"
+ style="width: {{percent component.measures.info_issues component.measures.max_issues}}%;"></div>
+ </div>
+ </div>
+ <i class="icon-dropdown"></i>
+ </a>
+
+ <a data-scope="coverage" class="component-viewer-header-measures-expand">
+ {{#if component.measures.coverage}}
+ <div class="component-viewer-header-measure">
+ <span class="component-viewer-header-measure-value">{{component.measures.coverage}}</span>
+ <span class="component-viewer-header-measure-label">{{t 'metric.coverage.name'}}</span>
+ </div>
+ {{/if}}
+ <i class="icon-dropdown"></i>
+ </a>
+
+ <a data-scope="duplications" class="component-viewer-header-measures-expand">
+ {{#if component.measures.duplication_density}}
+ <div class="component-viewer-header-measure">
+ <span class="component-viewer-header-measure-value">{{component.measures.duplication_density}}</span>
+ <span class="component-viewer-header-measure-label">Duplications</span>
+ </div>
+ {{/if}}
+ <i class="icon-dropdown"></i>
+ </a>
+ </div>
+</div>
+
+
+
+<div data-scope="basic" class="component-viewer-header-expanded-bar">
+ {{> '_basic-header'}}
+</div>
+
+<div data-scope="issues" class="component-viewer-header-expanded-bar">
+ {{> '_issues-header'}}
+</div>
+
+<div data-scope="coverage" class="component-viewer-header-expanded-bar">
+ {{> '_coverage-header'}}
+</div>
+
+<div data-scope="duplications" class="component-viewer-header-expanded-bar">
+ {{> '_duplications-header'}}
+</div>
\ No newline at end of file
-<tr class="component-viewer-header">
- {{#if settings.coverage}}
- <th class="stat"></th>
- <th class="stat"></th>
- {{/if}}
- {{#if settings.duplications}}
- <th class="stat"></th>
- {{/if}}
- <th>
- <button class="button-clean button-full-size js-toggle-measures"><i class="icon-list"></i></button>
- </th>
- <th class="component-viewer-header-main">
- <div class="component-viewer-header-box">
- <div class="component-viewer-header-measure component-viewer-header-measure-main">
- <span class="component-viewer-header-measure-value">{{component.measures.ncloc.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.ncloc.name'}}</span>
- </div>
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Size</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><span class="item">
+ <span>Accessors</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Classes</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Functions</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Public API</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Statements</span>
+ <span class="number">X</span>
+ </span></li>
+ </ul>
+</div>
- {{#if component.measures.lines.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">{{component.measures.lines.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.lines.name'}}</span>
- </div>
- {{/if}}
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Lines</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><span class="item">
+ <span>Generated lines</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Generated lines of code</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Lines</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Lines of code</span>
+ <span class="number">X</span>
+ </span></li>
+ </ul>
+</div>
- {{#if component.measures.functions.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">{{component.measures.functions.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.functions.name'}}</span>
- </div>
- {{/if}}
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Complexity</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><span class="item">
+ <span>Complexity</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Complexity /class</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Complexity /file</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Complexity /function</span>
+ <span class="number">X</span>
+ </span></li>
+ </ul>
+</div>
- {{#if component.measures.accessors.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">{{component.measures.accessors.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.accessors.name'}}</span>
- </div>
- {{/if}}
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Design</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><span class="item">
+ <span>File dependencies to cut</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Package cycles</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Package dependencies to cut</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Package tangle index</span>
+ <span class="number">X</span>
+ </span></li>
+ </ul>
+</div>
- {{#if component.measures.classes.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">{{component.measures.classes.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.classes.name'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.complexity.frmt_val}}
- <div class="component-viewer-header-measure component-viewer-header-measure-extra">
- <span class="component-viewer-header-measure-value">{{component.measures.complexity.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.complexity.name'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.function_complexity.frmt_val}}
- <div class="component-viewer-header-measure component-viewer-header-measure-extra">
- <span class="component-viewer-header-measure-value">{{component.measures.function_complexity.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.function_complexity.name'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.comment_lines_density.frmt_val}}
- <div class="component-viewer-header-measure component-viewer-header-measure-extra">
- <span class="component-viewer-header-measure-value">{{component.measures.comment_lines_density.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.comment_lines_density.name'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.comment_lines.frmt_val}}
- <div class="component-viewer-header-measure component-viewer-header-measure-extra">
- <span class="component-viewer-header-measure-value">{{component.measures.comment_lines.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.comment_lines.name'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.public_documented_api_density.frmt_val}}
- <div class="component-viewer-header-measure component-viewer-header-measure-extra">
- <span class="component-viewer-header-measure-value">{{component.measures.public_documented_api_density.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.public_documented_api_density.name'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.public_undocumented_api.frmt_val}}
- <div class="component-viewer-header-measure component-viewer-header-measure-extra">
- <span class="component-viewer-header-measure-value">{{component.measures.public_undocumented_api.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.public_undocumented_api.name'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.public_api.frmt_val}}
- <div class="component-viewer-header-measure component-viewer-header-measure-extra">
- <span class="component-viewer-header-measure-value">{{component.measures.public_api.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.public_api.name'}}</span>
- </div>
- {{/if}}
-
- <div class="component-viewer-header-filter">
- <button class="button-clean js-time-changes">
- <i class="icon-period"></i>
- <i class="icon-dropdown"></i>
- </button>
- <span class="component-viewer-header-measure-label">Time changes</span>
- </div>
- </div>
- </th>
-</tr>
\ No newline at end of file
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Documentation</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><span class="item">
+ <span>Comment lines</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Comments (%)</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Public documented API (%)</span>
+ <span class="number">X</span>
+ </span></li>
+ <li><span class="item">
+ <span>Public undocumented API</span>
+ <span class="number">X</span>
+ </span></li>
+ </ul>
+</div>
\ No newline at end of file
-<tr class="component-viewer-header">
- {{#if settings.coverage}}
- <th class="stat"></th>
- <th class="stat"></th>
- {{/if}}
- {{#if settings.duplications}}
- <th class="stat"></th>
- {{/if}}
- <th>
- <button class="button-clean button-full-size"><i class="icon-list"></i></button>
- </th>
- <th class="component-viewer-header-main">
- <div class="component-viewer-header-box">
- <div class="component-viewer-header-measure component-viewer-header-measure-main">
- <span class="component-viewer-header-measure-value">{{component.measures.coverage.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.coverage.name'}}</span>
- </div>
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">{{component.measures.line_coverage.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.line_coverage.name'}}</span>
- </div>
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">{{component.measures.branch_coverage.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.branch_coverage.name'}}</span>
- </div>
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Unit Tests</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><a class="item">
+ <span>Line Coverage</span>
+ <span class="number">93.6%</span>
+ </a></li>
+ <li><a class="item">
+ <span>Branch Coverage</span>
+ <span class="number">100%</span>
+ </a></li>
+ </ul>
+</div>
- <div class="component-viewer-header-filter">
- <button class="button-clean js-time-changes">
- <i class="icon-period"></i>
- <i class="icon-dropdown"></i>
- </button>
- <span class="component-viewer-header-measure-label">Time changes</span>
- </div>
- </div>
- </th>
-</tr>
\ No newline at end of file
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Integration Tests</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><a class="item">
+ <span>Line Coverage</span>
+ <span class="number">47.2%</span>
+ </a></li>
+ <li><a class="item">
+ <span>Branch Coverage</span>
+ <span class="number">25%</span>
+ </a></li>
+ </ul>
+</div>
\ No newline at end of file
--- /dev/null
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Duplications</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><a class="item">
+ <span>Lines</span>
+ <span class="number">76</span>
+ </a></li>
+ <li><a class="item">
+ <span>Duplicated Lines</span>
+ <span class="number">16</span>
+ </a></li>
+ <li><a class="item">
+ <span>Duplicated Blocks</span>
+ <span class="number">2</span>
+ </a></li>
+ </ul>
+</div>
\ No newline at end of file
-<tr class="component-viewer-header">
- {{#if settings.coverage}}
- <th class="stat"></th>
- <th class="stat"></th>
- {{/if}}
- {{#if settings.duplications}}
- <th class="stat"></th>
- {{/if}}
- <th></th>
- <th class="component-viewer-header-main">
- <div class="component-viewer-header-box">
-
- <div class="component-viewer-header-measure component-viewer-header-measure-main">
- <span class="component-viewer-header-measure-value">{{component.measures.violations.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.violations.name'}}</span>
- </div>
-
- <div class="component-viewer-header-measure component-viewer-header-measure-main">
- <span class="component-viewer-header-measure-value">{{component.measures.sqale_index.frmt_val}}</span>
- <span class="component-viewer-header-measure-label">{{t 'metric.sqale_index.name'}}</span>
- </div>
-
- {{#if component.measures.blocker_violations.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">
- <i class="icon-severity-blocker"></i>
- {{component.measures.blocker_violations.frmt_val}}
- </span>
- <span class="component-viewer-header-measure-label">{{t 'severity.BLOCKER'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.critical_violations.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">
- <i class="icon-severity-critical"></i>
- {{component.measures.critical_violations.frmt_val}}
- </span>
- <span class="component-viewer-header-measure-label">{{t 'severity.CRITICAL'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.major_violations.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">
- <i class="icon-severity-major"></i>
- {{component.measures.major_violations.frmt_val}}
- </span>
- <span class="component-viewer-header-measure-label">{{t 'severity.MAJOR'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.minor_violations.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">
- <i class="icon-severity-minor"></i>
- {{component.measures.minor_violations.frmt_val}}
- </span>
- <span class="component-viewer-header-measure-label">{{t 'severity.MINOR'}}</span>
- </div>
- {{/if}}
-
- {{#if component.measures.info_violations.frmt_val}}
- <div class="component-viewer-header-measure">
- <span class="component-viewer-header-measure-value">
- <i class="icon-severity-info"></i>
- {{component.measures.info_violations.frmt_val}}
- </span>
- <span class="component-viewer-header-measure-label">{{t 'severity.INFO'}}</span>
- </div>
- {{/if}}
-
- <div class="component-viewer-header-filter">
- <button class="button-clean js-time-changes">
- <i class="icon-period"></i>
- <i class="icon-dropdown"></i>
- </button>
- <span class="component-viewer-header-measure-label">Time changes</span>
- </div>
-
- <div class="component-viewer-header-filter">
- <button class="button-clean">
- <i class="icon-filter"></i>
- <i class="icon-dropdown"></i>
- </button>
- <span class="component-viewer-header-measure-label">All issues</span>
- </div>
- </div>
- </th>
-</tr>
\ No newline at end of file
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">Rules</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><a class="item">
+ <span>Array designators "[]" should be located after the type in method signatures</span>
+ <span class="number">2</span>
+ </a></li>
+ <li><a class="item">
+ <span>Avoid Array Loops</span>
+ <span class="number">1</span>
+ </a></li>
+ <li><a class="item">
+ <span>Useless Operation On Immutable</span>
+ <span class="number">4</span>
+ </a></li>
+ </ul>
+</div>
+<div class="component-viewer-header-expanded-bar-section">
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><a class="item">
+ <span><i class="icon-severity-blocker"></i> {{t 'severity.BLOCKER'}}</span>
+ <span class="number">{{component.measures.blocker_issues}}</span>
+ </a></li>
+ <li><a class="item">
+ <span><i class="icon-severity-critical"></i> {{t 'severity.CRITICAL'}}</span>
+ <span class="number">{{component.measures.critical_issues}}</span>
+ </a></li>
+ <li><a class="item">
+ <span><i class="icon-severity-major"></i> {{t 'severity.MAJOR'}}</span>
+ <span class="number">{{component.measures.major_issues}}</span>
+ </a></li>
+ <li><a class="item">
+ <span><i class="icon-severity-minor"></i> {{t 'severity.MINOR'}}</span>
+ <span class="number">{{component.measures.minor_issues}}</span>
+ </a></li>
+ <li><a class="item">
+ <span><i class="icon-severity-info"></i> {{t 'severity.INFO'}}</span>
+ <span class="number">{{component.measures.info_issues}}</span>
+ </a></li>
+ </ul>
+</div>
+<div class="component-viewer-header-expanded-bar-section">
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><a class="item">
+ <span>Current issue</span>
+ </a></li>
+ <li><a class="item">
+ <span>False Positive</span>
+ <span class="number">3</span>
+ </a></li>
+ </ul>
+</div>
\ No newline at end of file
<div class="component-viewer-workspace"></div>
+<div class="component-viewer-header"></div>
<div class="component-viewer-source"></div>
\ No newline at end of file
-<table class="code" cellpadding="0" cellspacing="0">
- <thead>
- <tr>
+<table class="code">
+ <tr class="row row-hidden" data-line-number="0">
{{#if settings.coverage}}
- <th class="stat"></th>
- <th class="stat"></th>
+ <td class="stat coverage-tests"></td>
+ <td class="stat coverage-conditions"></td>
{{/if}}
{{#if settings.duplications}}
+ <td class="stat"></td>
+ {{/if}}
+ {{#if settings.scm}}
<th class="stat"></th>
{{/if}}
- <th class="stat settings-toggle">
- <button class="button-clean js-toggle-settings">
- <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>
- <li>
- <input id="source-scm" type="checkbox" {{#if settings.scm}}checked{{/if}}>
- <label for="source-scm">SCM</label>
- </li>
- <li>
- <input id="source-workspace" type="checkbox" {{#if settings.workspace}}checked{{/if}}>
- <label for="source-workspace">Workspace</label>
- </li>
- </ul>
-
- {{#if component.projectLongName}}
- {{qualifierIcon 'TRK'}} <span class="component-viewer-title">{{component.projectLongName}}</span>
- <span class="component-viewer-title-separator">—</span>
- {{/if}}
- {{qualifierIcon component.qualifier}} <span class="component-viewer-title">{{component.lname}}</span>
-
- <a class="icon-not-favorite" href="#" onclick="toggleFav({{component.id}}, this); return false;"
- title="Click to add to favourites"></a>
- </th>
+ <td class="stat lid"></td>
+ <td class="line"></td>
</tr>
- {{! headers }}
- {{> '_basic-header'}}
- {{#if settings.issues}}{{> '_issues-header'}}{{/if}}
- {{#if settings.coverage}}{{> '_coverage-header'}}{{/if}}
-
- </thead>
- <tbody>
- <tr class="row row-hidden" data-line-number="0">
- {{#if settings.coverage}}
- <td class="stat coverage-tests"></td>
- <td class="stat coverage-conditions"></td>
- {{/if}}
- {{#if settings.duplications}}
- <td class="stat"></td>
- {{/if}}
- <td class="stat lid"></td>
- <td class="line"></td>
- </tr>
-
- {{#each source}}
- {{#if show}}
- <tr class="row {{#if ../../settings.coverage}}{{#if coverageStatus}}coverage-{{coverageStatus}}{{/if}}{{/if}}"
- data-line-number="{{lineNumber}}">
-
- {{#if ../../settings.coverage}}
- <td class="stat coverage-tests">
- {{#if coverage}}
- <span title="Line is covered by {{coverage}} tests">{{coverage}}</span>
- {{/if}}
- </td>
-
- <td class="stat coverage-conditions">
- {{#if coverageConditions}}
- {{#if conditions}}
- <span title="{{coverageConditions}} branches are covered by tests">
- {{coverageConditions}}/{{conditions}}
- </span>
- {{/if}}
+ {{#each source}}
+ {{#if show}}
+ <tr class="row {{#if ../../settings.coverage}}{{#if coverageStatus}}coverage-{{coverageStatus}}{{/if}}{{/if}}"
+ data-line-number="{{lineNumber}}">
+
+ {{#if ../../settings.coverage}}
+ <td class="stat coverage-tests">
+ {{#if coverage}}
+ <span title="Line is covered by {{coverage}} tests">{{coverage}}</span>
+ {{/if}}
+ </td>
+
+ <td class="stat coverage-conditions">
+ {{#if coverageConditions}}
+ {{#if conditions}}
+ <span title="{{coverageConditions}} branches are covered by tests">
+ {{coverageConditions}}/{{conditions}}
+ </span>
{{/if}}
- </td>
- {{/if}}
-
- {{#if ../../settings.duplications}}
- <td class="stat duplications">
- {{#each duplications}}
- <span class="duplication {{#if this}}duplication-exists{{/if}}"></span>
- {{/each}}
- </td>
- {{/if}}
-
- <td class="stat lid">{{lineNumber}}</td>
-
- <td class="line"><pre>{{{code}}}</pre></td>
- </tr>
- {{/if}}
- {{/each}}
- </tbody>
+ {{/if}}
+ </td>
+ {{/if}}
+
+ {{#if ../../settings.duplications}}
+ <td class="stat duplications">
+ {{#each duplications}}
+ <span class="duplication {{#if this}}duplication-exists{{/if}}"></span>
+ {{/each}}
+ </td>
+ {{/if}}
+
+ {{#if ../../settings.scm}}
+ <td class="stat {{#if scm}}scm{{/if}}">
+ {{#if scm}}
+ <span class="scm-date">{{scm.date}}</span>
+ <span class="scm-author" title="{{scm.author}}">{{scm.author}}</span>
+ {{/if}}
+ </td>
+ {{/if}}
+
+ <td class="stat lid">{{lineNumber}}</td>
+
+ <td class="line"><pre>{{{code}}}</pre></td>
+ </tr>
+ {{/if}}
+ {{/each}}
</table>
\ No newline at end of file
);
});
+ Handlebars.registerHelper('percent', function(value, total) {
+ return value / total * 100;
+ });
+
Handlebars.registerHelper('eq', function(v1, v2, options) {
return v1 == v2 ? options.fn(this) : options.inverse(this);
});
.component-viewer {
width: 100%;
min-width: 600px;
- border: 1px solid @barBorderColor;
border-left-width: 0;
.box-sizing(border-box);
}
.code {
width: 100%;
- border-left: 1px solid @barBorderColor;
+ border: 1px solid @barBorderColor;
}
.code th {
background-position: bottom;
}
+ .code .scm {
+ text-align: left;
+
+ .scm-date {
+ display: inline-block;
+ vertical-align: middle;
+ padding: 2px 4px;
+ line-height: 1;
+ background-color: @barBorderColor;
+ }
+
+ .scm-author {
+ display: inline-block;
+ vertical-align: middle;
+ max-width: 120px;
+ padding: 2px 0;
+ line-height: 1;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ }
+
.code .row {
&.coverage-green td.stat {
}
+
+
.component-viewer-header {
+ margin-bottom: 10px;
+}
- & > th {
- background-color: @barBackgroundColor;
- border-top: 1px solid @barBorderColor;
- border-bottom: 1px solid @barBorderColor;
- }
+.component-viewer-header-bar {
+ .clearfix;
+ border: 1px solid @barBorderColor;
+ background-color: @barBackgroundColor;
+}
- .button-full-size {
- .size(100%, 100%);
- margin: 0;
+.component-viewer-header-bar + .component-viewer-header-bar {
+ border-top: 1px solid @barBorderColor;
+}
+
+.component-viewer-header-component {
+ float: left;
+ padding: 10px;
+}
+
+.component-viewer-header-component-project {
+ color: #777;
+ font-size: @smallFontSize;
+ margin-bottom: 4px;
+}
+
+.component-viewer-header-component-name {
+ font-weight: 600;
+}
+
+.component-viewer-header-measures {
+ float: right;
+}
+
+.component-viewer-header-measures-expand {
+ float: left;
+ padding: 10px 20px;
+ border-left: 1px solid transparent;
+ .trans(background);
+
+ &:hover { background-color: @barBorderColor; }
+
+ &:active, &.active {
+ margin-bottom: -1px;
+ border-bottom: 1px solid #fff;
+ border-left-color: @barBorderColor;
+ background-color: #fff;
}
}
-.component-viewer-header-main {
- font-size: 0;
- padding: 4px 0 4px 5px;
+.component-viewer-header-measures-expand + .component-viewer-header-measures-expand {
+ border-left-color: @barBorderColor;
}
-.component-viewer-header-box { margin-bottom: -20px; }
+.component-viewer-header-measures-expand .icon-dropdown {
+ margin-left: 6px;
+ margin-right: -10px;
+}
.component-viewer-header-measure {
display: inline-block;
- vertical-align: bottom;
- margin: 0 20px 20px 0;
+ vertical-align: middle;
font-size: @baseFontSize;
}
-.component-viewer-header-measure-extra {
- display: none;
-}
-
-.component-viewer-header-full .component-viewer-header-measure-extra {
- display: inline-block;
+.component-viewer-header-measure + .component-viewer-header-measure {
+ margin-left: 15px;
}
.component-viewer-header-measure-label {
margin-top: 2px;
color: #777;
font-size: @smallFontSize;
-
- &:after { content: ""; }
}
.component-viewer-header-measure-value {
display: block;
color: @baseFontColor;
- font-size: 14px;
+ font-size: 18px;
+
+ i { top: -3px; }
}
-.component-viewer-header-measure-main {
+.component-viewer-header-measure-issues {
+ width: 60px;
+}
+
+.component-viewer-header-measure-issue {
+ min-width: 1px;
+ height: 6px;
- .component-viewer-header-measure-value {
- font-size: 24px;
+ &.s-blocker { background-color: @severityBlockerColor; }
+ &.s-critical { background-color: @severityCriticalColor; }
+ &.s-major { background-color: @severityMajorColor; }
+ &.s-minor { background-color: @severityMinorColor; }
+ &.s-info { background-color: @severityInfoColor; }
+}
+
+.component-viewer-header-measure-issue + .component-viewer-header-measure-issue {
+ margin-top: 1px;
+}
+
+.component-viewer-header-links {
+ float: right;
+ padding: 8px 10px;
+ border-left: 1px solid @barBorderColor;
+
+ a {
+ float: left;
+ clear: left;
+ }
+
+ a + a {
+ margin-top: 9px;
}
}
-.component-viewer-header-filter {
- display: inline-block;
- vertical-align: bottom;
- margin: 0 20px 20px 0;
+.component-viewer-header-expanded-bar {
+ display: none;
+ .clearfix;
+ padding: 10px;
+ border: 1px solid @barBorderColor;
+ border-top: none;
+ background-color: #fff;
+}
+
+.component-viewer-header-expanded-bar-section {
+ float: left;
+ min-width: 150px;
+ max-width: 250px;
+}
+
+.component-viewer-header-expanded-bar-section + .component-viewer-header-expanded-bar-section {
+ margin-left: 20px;
padding-left: 20px;
border-left: 1px solid @barBorderColor;
- font-size: @baseFontSize;
- color: @darkBlue;
+}
- .button-clean { height: auto; }
+.component-viewer-header-expanded-bar-section-title {
+ margin-bottom: 6px;
+ color: #777;
+ font-size: @smallFontSize;
+}
+
+.component-viewer-header-expanded-bar-section-list {
+
+ & > li > .item {
+ position: relative;
+ display: block;
+ padding: 2px 25px 2px 5px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ & > .number {
+ position: absolute;
+ right: 5px;
+ }
+ }
+
+ & > li > a {
+ .trans;
+
+ &:hover { background-color: @barBackgroundColor; }
+ }
}
content: "\f073";
font-size: @iconSmallFontSize;
}
+.icon-favorite { font-size: @iconFontSize; }
.icon-favorite:before {
content: "\f005";
color: @orange;
font-size: @iconFontSize;
}
+.icon-not-favorite { font-size: @iconFontSize; }
.icon-not-favorite:before {
content: "\f005";
color: @darkGrey;
content: "\f03a";
font-size: @iconFontSize;
}
+.icon-detach:before {
+ content: "\f08e";
+ font-size: @iconSmallFontSize;
+}
/*