component_viewer.transition.covers=Covers
component_viewer.transition.duplication=Duplicated By
-component_viewer.x_lines_are_covered={0} lines are covered
+component_viewer.x_lines_are_covered={0} lines are covered
\ No newline at end of file
name: x.name
subname: x.dir
active: file.key == key
- if method?
- @options.main.component.set 'selectedTest', method
- @options.main._open key
+ @options.main._open(key).done =>
+ @options.main.headerView.enableBar('tests').done =>
+ if method?
+ @options.main.headerView.enableUnitTest method
serializeData: ->
define [
'backbone.marionette'
'templates/component-viewer'
- 'component-viewer/covered-files-popup'
+
+ 'component-viewer/header/basic-header'
+ 'component-viewer/header/issues-header'
+ 'component-viewer/header/coverage-header'
+ 'component-viewer/header/duplications-header'
+ 'component-viewer/header/tests-header'
+
+ 'component-viewer/time-changes-popup'
+
'common/handlebars-extensions'
], (
Marionette
Templates
- CoveredFilesPopupView
+
+ BasicHeaderView
+ IssuesHeaderView
+ CoverageHeaderView
+ DuplicationsHeaderView
+ TestsHeaderView
+
+ TimeChangesPopupView
) ->
$ = jQuery
API_FAVORITE = "#{baseUrl}/api/favourites"
- API_TESTS_COVERED_FILES = "#{baseUrl}/api/tests/covered_files"
+ BARS = [
+ { scope: 'basic', view: BasicHeaderView }
+ { scope: 'issues', view: IssuesHeaderView }
+ { scope: 'coverage', view: CoverageHeaderView }
+ { scope: 'duplications', view: DuplicationsHeaderView }
+ { scope: 'tests', view: TestsHeaderView }
+ ]
- class HeaderView extends Marionette.Layout
+ class extends Marionette.Layout
template: Templates['header']
+ regions:
+ barRegion: '.component-viewer-header-expanded-bar'
+
+
ui:
expandLinks: '.component-viewer-header-measures-expand'
- expandedBars: '.component-viewer-header-expanded-bar'
+ expandedBar: '.component-viewer-header-expanded-bar'
+ spinnerBar: '.component-viewer-header-expanded-bar[data-scope=spinner]'
unitTests: '.js-unit-test'
'click .js-toggle-duplications': 'toggleDuplications'
'click .js-toggle-scm': 'toggleSCM'
- 'click .js-issues-bulk-change': 'issuesBulkChange'
-
- 'click .js-filter-current-issue': 'filterByCurrentIssue'
- 'click .js-filter-all-issues': 'filterByAllIssues'
- 'click .js-filter-rule': 'filterByRule'
- 'click .js-filter-fixed-issues': 'filterByFixedIssues'
- 'click .js-filter-unresolved-issues': 'filterByUnresolvedIssues'
- 'click .js-filter-false-positive-issues': 'filterByFalsePositiveIssues'
- 'click .js-filter-BLOCKER-issues': 'filterByBlockerIssues'
- 'click .js-filter-CRITICAL-issues': 'filterByCriticalIssues'
- 'click .js-filter-MAJOR-issues': 'filterByMajorIssues'
- 'click .js-filter-MINOR-issues': 'filterByMinorIssues'
- 'click .js-filter-INFO-issues': 'filterByInfoIssues'
-
- 'click .js-filter-lines-to-cover': 'filterByLinesToCover'
- 'click .js-filter-covered-lines': 'filterByCoveredLines'
- 'click .js-filter-uncovered-lines': 'filterByUncoveredLines'
- 'click .js-filter-branches-to-cover': 'filterByBranchesToCover'
- 'click .js-filter-covered-branches': 'filterByCoveredBranches'
- 'click .js-filter-uncovered-branches': 'filterByUncoveredBranches'
- 'click .js-filter-lines-to-cover-it': 'filterByLinesToCoverIT'
- 'click .js-filter-covered-lines-it': 'filterByCoveredLinesIT'
- 'click .js-filter-uncovered-lines-it': 'filterByUncoveredLinesIT'
- 'click .js-filter-branches-to-cover-it': 'filterByBranchesToCoverIT'
- 'click .js-filter-covered-branches-it': 'filterByCoveredBranchesIT'
- 'click .js-filter-uncovered-branches-it': 'filterByUncoveredBranchesIT'
-
- 'click .js-filter-duplications': 'filterByDuplications'
-
- 'click @ui.unitTests': 'showCoveredFiles'
+ 'click .component-viewer-header-time-changes a': 'showTimeChangesPopup'
initialize: (options) ->
options.main.settings.on 'change', => @changeSettings()
+ @state = options.main.state
+ @component = options.main.component
+ @settings = options.main.component
onRender: ->
@delegateEvents()
- if @options.main.component.get('q') == 'UTS'
- @ui.expandLinks.filter("[data-scope=tests]").click()
toggleFavorite: ->
- component = @options.main.component
+ component = @component
if component.get 'fav'
$.ajax
url: "#{API_FAVORITE}/#{component.get 'key'}"
@render()
+ showBarSpinner: ->
+ @ui.spinnerBar.addClass 'active'
+
+
+ hideBarSpinner: ->
+ @ui.spinnerBar.removeClass 'active'
+
+
+ resetBars: ->
+ @state.set 'activeHeaderTab', null
+ @ui.expandLinks.removeClass 'active'
+ @ui.expandedBar.removeClass 'active'
+ @barRegion.reset()
+
+
+ enableBar: (scope) ->
+ @ui.expandedBar.addClass 'active'
+ requests = []
+ unless @state.get 'hasMeasures'
+ requests.push @options.main.requestMeasures @options.main.key
+ if @component.get('isUnitTest') && !@state.get('hasTests')
+ requests.push @options.main.requestTests @options.main.key
+ $.when.apply($, requests).done =>
+ @state.set 'activeHeaderTab', scope
+ bar = _.findWhere BARS, scope: scope
+ @barRegion.show new bar.view
+ state: @state, component: @component, settings: @settings, source: @model, header: @
+ @ui.expandLinks.filter("[data-scope=#{scope}]").addClass 'active'
+
showExpandedBar: (e) ->
el = $(e.currentTarget)
active = el.is '.active'
- @ui.expandLinks.removeClass 'active'
- @ui.expandedBars.hide()
+ @resetBars()
unless active
el.addClass 'active'
scope = el.data 'scope'
- unless @options.main.component.has 'msr'
- req = @options.main.requestMeasures(@options.main.key)
- if @options.main.component.get('q') == 'UTS'
- req = $.when req, @options.main.requestTests(@options.main.key)
- req.done =>
- @render()
- @ui.expandLinks.filter("[data-scope=#{scope}]").addClass 'active'
- @ui.expandedBars.filter("[data-scope=#{scope}]").show()
-
- method = @options.main.component.get 'selectedTest'
- if method?
- @options.main.component.unset 'selectedTest'
- @ui.unitTests.filter("[data-name=#{method}]").click().addClass('active')
- else
- @ui.expandedBars.filter("[data-scope=#{scope}]").show()
+ @enableBar scope
changeSettings: ->
toggleWorkspace: (e) -> @toggleSetting e, @options.main.showWorkspace, @options.main.hideWorkspace
- issuesBulkChange: ->
- issues = @model.get('activeIssues')?.map (issue) -> issue.key
- if issues.length > 0
- url = "#{baseUrl}/issues/bulk_change_form?issues=#{issues.join()}"
- openModalWindow url, {}
+ showTimeChangesPopup: (e) ->
+ e.stopPropagation()
+ $('body').click()
+ popup = new TimeChangesPopupView
+ triggerEl: $(e.currentTarget)
+ main: @options.main
+ popup.render()
filterLines: (e, methodName, extra) ->
method.call @options.main, extra
- # Issues
- filterByCurrentIssue: (e) -> @filterLines e, 'filterByCurrentIssue'
- filterByAllIssues: (e) -> @filterLines e, 'filterByAllIssues'
- filterByFixedIssues: (e) -> @filterLines e, 'filterByFixedIssues'
- filterByUnresolvedIssues: (e) -> @filterLines e, 'filterByUnresolvedIssues'
- filterByFalsePositiveIssues: (e) -> @filterLines e, 'filterByFalsePositiveIssues'
-
- filterByRule: (e) -> @filterLines e, 'filterByRule', $(e.currentTarget).data 'rule'
-
- filterByBlockerIssues: (e) -> @filterLines e, 'filterByBlockerIssues'
- filterByCriticalIssues: (e) -> @filterLines e, 'filterByCriticalIssues'
- filterByMajorIssues: (e) -> @filterLines e, 'filterByMajorIssues'
- filterByMinorIssues: (e) -> @filterLines e, 'filterByMinorIssues'
- filterByInfoIssues: (e) -> @filterLines e, 'filterByInfoIssues'
-
-
- # Coverage
- filterByLinesToCover: (e) -> @filterLines e, 'filterByLinesToCover'
- filterByCoveredLines: (e) -> @filterLines e, 'filterByCoveredLines'
- filterByUncoveredLines: (e) -> @filterLines e, 'filterByUncoveredLines'
- filterByBranchesToCover: (e) -> @filterLines e, 'filterByBranchesToCover'
- filterByCoveredBranches: (e) -> @filterLines e, 'filterByCoveredBranches'
- filterByUncoveredBranches: (e) -> @filterLines e, 'filterByUncoveredBranches'
-
- filterByLinesToCoverIT: (e) -> @filterLines e, 'filterByLinesToCoverIT'
- filterByCoveredLinesIT: (e) -> @filterLines e, 'filterByCoveredLinesIT'
- filterByUncoveredLinesIT: (e) -> @filterLines e, 'filterByUncoveredLinesIT'
- filterByBranchesToCoverIT: (e) -> @filterLines e, 'filterByBranchesToCoverIT'
- filterByCoveredBranchesIT: (e) -> @filterLines e, 'filterByCoveredBranchesIT'
- filterByUncoveredBranchesIT: (e) -> @filterLines e, 'filterByUncoveredBranchesIT'
-
-
- # Duplications
- filterByDuplications: (e) -> @filterLines e, 'filterByDuplications'
-
-
- showCoveredFiles: (e) ->
- e.stopPropagation()
- $('body').click()
- @$('.component-viewer-header-expanded-bar-section-list .active').removeClass 'active'
- testName = $(e.currentTarget).data 'name'
- test = _.findWhere @options.main.component.get('tests'), name: testName
- key = @options.main.component.get('key')
- $.get API_TESTS_COVERED_FILES, key: key, test: testName, (data) =>
- popup = new CoveredFilesPopupView
- triggerEl: $(e.currentTarget)
- collection: new Backbone.Collection data.files
- test: test
- main: @options.main
- popup.render()
-
-
serializeData: ->
- component = @options.main.component.toJSON()
+ component = @component.toJSON()
if component.measures
component.measures.maxIssues = Math.max(
component.measures.fBlockerIssues || 0
component.measures.fInfoIssues || 0
)
- if component.severities
- order = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO']
- component.severities = _.sortBy component.severities, (s) -> order.indexOf s[0]
-
settings: @options.main.settings.toJSON()
+ state: @state.toJSON()
showSettings: @showSettings
component: component
- currentIssue: @options.main.currentIssue
\ No newline at end of file
+ currentIssue: @options.main.currentIssue
+ period: @options.main.period?.toJSON()
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone.marionette'
+], (
+ Marionette
+) ->
+
+ class extends Marionette.ItemView
+
+ initialize: (options) ->
+ super
+ @state = options.state
+ @component = options.component
+ @settings = options.settings
+ @source = options.source
+ @header = options.header
+
+
+ serializeData: ->
+ _.extend super,
+ state: @state.toJSON()
+ component: @component.toJSON()
+ settings: @settings.toJSON()
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/component-viewer'
+ 'component-viewer/header/base-header'
+], (
+ Marionette
+ Templates
+ BaseHeaderView
+) ->
+
+
+ class extends BaseHeaderView
+ template: Templates['basic-header']
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/component-viewer'
+ 'component-viewer/header/base-header'
+], (
+ Marionette
+ Templates
+ BaseHeaderView
+) ->
+
+
+ class extends BaseHeaderView
+ template: Templates['coverage-header']
+
+
+ events:
+ 'click .js-filter-lines-to-cover': 'filterByLinesToCover'
+ 'click .js-filter-uncovered-lines': 'filterByUncoveredLines'
+ 'click .js-filter-branches-to-cover': 'filterByBranchesToCover'
+ 'click .js-filter-uncovered-branches': 'filterByUncoveredBranches'
+ 'click .js-filter-lines-to-cover-it': 'filterByLinesToCoverIT'
+ 'click .js-filter-uncovered-lines-it': 'filterByUncoveredLinesIT'
+ 'click .js-filter-branches-to-cover-it': 'filterByBranchesToCoverIT'
+ 'click .js-filter-uncovered-branches-it': 'filterByUncoveredBranchesIT'
+
+
+ filterByLinesToCover: (e) -> @header.filterLines e, 'filterByLinesToCover'
+ filterByCoveredLines: (e) -> @header.filterLines e, 'filterByCoveredLines'
+ filterByUncoveredLines: (e) -> @header.filterLines e, 'filterByUncoveredLines'
+ filterByBranchesToCover: (e) -> @header.filterLines e, 'filterByBranchesToCover'
+ filterByCoveredBranches: (e) -> @header.filterLines e, 'filterByCoveredBranches'
+ filterByUncoveredBranches: (e) -> @header.filterLines e, 'filterByUncoveredBranches'
+
+ filterByLinesToCoverIT: (e) -> @header.filterLines e, 'filterByLinesToCoverIT'
+ filterByCoveredLinesIT: (e) -> @header.filterLines e, 'filterByCoveredLinesIT'
+ filterByUncoveredLinesIT: (e) -> @header.filterLines e, 'filterByUncoveredLinesIT'
+ filterByBranchesToCoverIT: (e) -> @header.filterLines e, 'filterByBranchesToCoverIT'
+ filterByCoveredBranchesIT: (e) -> @header.filterLines e, 'filterByCoveredBranchesIT'
+ filterByUncoveredBranchesIT: (e) -> @header.filterLines e, 'filterByUncoveredBranchesIT'
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/component-viewer'
+ 'component-viewer/header/base-header'
+], (
+ Marionette
+ Templates
+ BaseHeaderView
+) ->
+
+
+ class extends BaseHeaderView
+ template: Templates['duplications-header']
+
+
+ events:
+ 'click .js-filter-duplications': 'filterByDuplications'
+
+
+ filterByDuplications: (e) -> @header.filterLines e, 'filterByDuplications'
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/component-viewer'
+ 'component-viewer/header/base-header'
+], (
+ Marionette
+ Templates
+ BaseHeaderView
+) ->
+
+ $ = jQuery
+
+
+ class extends BaseHeaderView
+ template: Templates['issues-header']
+
+
+ events:
+ 'click .js-issues-bulk-change': 'issuesBulkChange'
+
+ 'click .js-filter-current-issue': 'filterByCurrentIssue'
+ 'click .js-filter-all-issues': 'filterByAllIssues'
+ 'click .js-filter-rule': 'filterByRule'
+ 'click .js-filter-fixed-issues': 'filterByFixedIssues'
+ 'click .js-filter-unresolved-issues': 'filterByUnresolvedIssues'
+ 'click .js-filter-false-positive-issues': 'filterByFalsePositiveIssues'
+ 'click .js-filter-BLOCKER-issues': 'filterByBlockerIssues'
+ 'click .js-filter-CRITICAL-issues': 'filterByCriticalIssues'
+ 'click .js-filter-MAJOR-issues': 'filterByMajorIssues'
+ 'click .js-filter-MINOR-issues': 'filterByMinorIssues'
+ 'click .js-filter-INFO-issues': 'filterByInfoIssues'
+
+
+ issuesBulkChange: ->
+ issues = @source.get('activeIssues')?.map (issue) -> issue.key
+ if issues.length > 0
+ url = "#{baseUrl}/issues/bulk_change_form?issues=#{issues.join()}"
+ openModalWindow url, {}
+
+
+ filterByCurrentIssue: (e) -> @header.filterLines e, 'filterByCurrentIssue'
+ filterByAllIssues: (e) -> @header.filterLines e, 'filterByAllIssues'
+ filterByFixedIssues: (e) -> @header.filterLines e, 'filterByFixedIssues'
+ filterByUnresolvedIssues: (e) -> @header.filterLines e, 'filterByUnresolvedIssues'
+ filterByFalsePositiveIssues: (e) -> @header.filterLines e, 'filterByFalsePositiveIssues'
+
+ filterByRule: (e) -> @header.filterLines e, 'filterByRule', $(e.currentTarget).data 'rule'
+
+ filterByBlockerIssues: (e) -> @header.filterLines e, 'filterByBlockerIssues'
+ filterByCriticalIssues: (e) -> @header.filterLines e, 'filterByCriticalIssues'
+ filterByMajorIssues: (e) -> @header.filterLines e, 'filterByMajorIssues'
+ filterByMinorIssues: (e) -> @header.filterLines e, 'filterByMinorIssues'
+ filterByInfoIssues: (e) -> @header.filterLines e, 'filterByInfoIssues'
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/component-viewer'
+ 'component-viewer/header/base-header'
+ 'component-viewer/covered-files-popup'
+], (
+ Marionette
+ Templates
+ BaseHeaderView
+ CoveredFilesPopupView
+) ->
+
+ $ = jQuery
+ API_TESTS_COVERED_FILES = "#{baseUrl}/api/tests/covered_files"
+
+
+ class extends BaseHeaderView
+ template: Templates['tests-header']
+
+
+ ui:
+ unitTests: '.js-unit-test'
+
+
+ events:
+ 'click @ui.unitTests': 'showCoveredFiles'
+
+
+ onRender: ->
+ @header.enableUnitTest = (testName) =>
+ @ui.unitTests.filter("[data-name=#{testName}]").click()
+
+
+ onClose: ->
+ delete @header.enableUnitTest
+
+
+ showCoveredFiles: (e) ->
+ e.stopPropagation()
+ $('body').click()
+ testName = $(e.currentTarget).data 'name'
+ test = _.findWhere @component.get('tests'), name: testName
+ key = @component.get('key')
+ $.get API_TESTS_COVERED_FILES, key: key, test: testName, (data) =>
+ popup = new CoveredFilesPopupView
+ triggerEl: $(e.currentTarget)
+ collection: new Backbone.Collection data.files
+ test: test
+ main: @options.main
+ popup.render()
\ No newline at end of file
'backbone'
'backbone.marionette'
'templates/component-viewer'
+
+ 'component-viewer/models/state'
+ 'component-viewer/models/component'
+ 'component-viewer/models/period'
+
+ 'component-viewer/mixins/main-issues'
+ 'component-viewer/mixins/main-coverage'
+ 'component-viewer/mixins/main-duplications'
+ 'component-viewer/mixins/main-scm'
+
'component-viewer/workspace'
'component-viewer/source'
'component-viewer/header'
Backbone
Marionette
Templates
+
+ State
+ Component
+ Period
+
+ IssuesMixin
+ CoverageMixin
+ DuplicationsMixin
+ SCMMixin
+
WorkspaceView
SourceView
HeaderView
API_COMPONENT = "#{baseUrl}/api/components/app"
API_SOURCES = "#{baseUrl}/api/sources/show"
- API_ISSUES = "#{baseUrl}/api/issues/search"
- API_COVERAGE = "#{baseUrl}/api/coverage/show"
- API_SCM = "#{baseUrl}/api/sources/scm"
API_MEASURES = "#{baseUrl}/api/resources"
- API_DUPLICATIONS = "#{baseUrl}/api/duplications/show"
API_TESTS = "#{baseUrl}/api/tests/show"
- LINES_AROUND_ISSUE = 4
- LINES_AROUND_COVERED_LINE = 1
- LINES_AROUND_DUPLICATION = 1
-
SOURCE_METRIC_LIST = 'accessors,classes,functions,statements,' +
'ncloc,lines,' +
'complexity,function_complexity,' +
- class ComponentViewer extends Marionette.Layout
+ class ComponentViewer extends utils.mixOf Marionette.Layout, IssuesMixin, CoverageMixin, DuplicationsMixin, SCMMixin
className: 'component-viewer'
template: Templates['layout']
@settings = new Backbone.Model @getDefaultSettings()
@settings.set options.settings
- @component = new Backbone.Model()
+ @state = new State()
+
+ @component = new Component()
@component.set options.component if options.component?
@workspace = new Backbone.Collection()
model: @source
main: @
- @requestIssuesOnce = false
+ @period = null
+ @periods = new Backbone.Collection [], model: Period
getDefaultSettings: ->
requestComponent: (key, clear = false) ->
+ STATE_FIELDS = ['canBulkChange', 'canMarkAsFavourite', 'scmAvailable']
+ COMPONENT_FIELDS = ['key', 'name', 'path', 'q', 'projectName', 'subProjectName', 'measures', 'fav']
+
$.get API_COMPONENT, key: key, (data) =>
+ # Component
@component.clear() if clear
- @component.set data
+ COMPONENT_FIELDS.forEach (f) => @component.set f, data[f]
@component.set 'dir', utils.splitLongName(data.path).dir
+ @component.set 'isUnitTest', data.q == 'UTS'
+
+ # State
+ stateAttributes = {}
+ STATE_FIELDS.forEach (f) -> stateAttributes[f] = data[f]
+ rules = data.rules.map (r) -> key: r[0], name: r[1], count: r[2]
+ stateAttributes.rules = _.sortBy rules, 'name'
+ severities = data.severities.map (r) -> key: r[0], name: r[1], count: r[2]
+ stateAttributes.severities = utils.sortSeverities severities
+ @state.clear silent: true
+ @state.set _.defaults stateAttributes, @state.defaults
+
+ # Periods
+ @periods.reset [{}]
+ data.periods.forEach (p) => @periods.add key: p[0], label: p[1], sinceDate: new Date p[2]
+ @period = @periods.at 0
requestMeasures: (key) ->
- unless @component.get('q') == 'UTS'
+ @state.set 'hasMeasures', true
+ unless @component.get 'isUnitTest'
metrics = [SOURCE_METRIC_LIST, COVERAGE_METRIC_LIST, ISSUES_METRIC_LIST, DUPLICATIONS_METRIC_LIST].join ','
else
metrics = [ISSUES_METRIC_LIST, TESTS_METRIC_LIST]
$.get API_MEASURES, resource: key, metrics: metrics, (data) =>
measuresList = data[0].msr || []
- measures = {}
- measuresList.forEach (m) -> measures[m.key] = m.frmt_val
-
- if measures['lines_to_cover']? && measures['uncovered_lines']?
- measures['covered_lines'] = measures['lines_to_cover'] - measures['uncovered_lines']
-
- if measures['conditions_to_cover']? && measures['uncovered_conditions']?
- measures['covered_conditions'] = measures['conditions_to_cover'] - measures['uncovered_conditions']
-
- if measures['it_lines_to_cover']? && measures['it_uncovered_lines']?
- measures['it_covered_lines'] = measures['it_lines_to_cover'] - measures['it_uncovered_lines']
-
- if measures['it_conditions_to_cover']? && measures['it_uncovered_conditions']?
- measures['it_covered_conditions'] = measures['it_conditions_to_cover'] - measures['it_uncovered_conditions']
-
- @component.set 'msr', measures
+ measures = @component.get 'measures'
+ measuresList.forEach (m) ->
+ measures[m.key] = m.frmt_val
+ @component.set 'measures', measures
requestSource: (key) ->
@source.set source: data.sources
- requestSCM: (key) ->
- $.get API_SCM, key: key, (data) =>
- @source.set scm: data.scm
-
-
- requestIssues: (key) ->
- options =
- components: key
- ps: 10000
- extra_fields: 'actions,transitions,assigneeName,actionPlanName'
- $.get API_ISSUES, options, (data) =>
- @requestIssuesOnce = true
- @source.set issues: data.issues
-
-
- requestCoverage: (key, type = 'UT') ->
- $.get API_COVERAGE, key: key, type: type, (data) =>
- @source.set coverage: data.coverage
-
-
- requestDuplications: (key) ->
- $.get API_DUPLICATIONS, key: key, (data) =>
- @source.set duplications: data.duplications
- @source.set duplicationFiles: data.files
-
-
requestTests: (key) ->
$.get API_TESTS, key: key, (data) =>
+ @state.set 'hasTests', true
@component.set 'tests', data.tests
if @settings.get('scm') then @showSCM() else @hideSCM()
- showCoverage: (store = false) ->
- @settings.set 'coverage', true
- @storeSettings() if store
- unless @source.has 'coverage'
- @requestCoverage(@key).done => @sourceView.render()
- else
- @sourceView.render()
-
-
- hideCoverage: (store = false) ->
- @settings.set 'coverage', false
- @storeSettings() if store
- @sourceView.render()
-
-
toggleWorkspace: (store = false) ->
if @settings.get 'workspace' then @hideWorkspace() else @showWorkspace()
@storeSettings() if store
@render()
- showIssues: (store = false, issue) ->
- @settings.set 'issues', true
- @storeSettings() if store
- if issue?
- @currentIssue = issue.key
- @source.set 'issues', [issue]
- @filterByCurrentIssue()
- @headerView.render()
- else
- @sourceView.render()
-
-
- hideIssues: (store = false) ->
- @settings.set 'issues', false
- @storeSettings() if store
- @sourceView.render()
-
-
- showDuplications: (store = false) ->
- @settings.set 'duplications', true
- @storeSettings() if store
- unless @source.has 'duplications'
- @requestDuplications(@key).done => @sourceView.render()
- else
- @sourceView.render()
-
-
- hideDuplications: (store = false) ->
- @settings.set 'duplications', false
- @storeSettings() if store
- @sourceView.render()
-
-
- showSCM: (store = false) ->
- @settings.set 'scm', true
- @storeSettings() if store
- unless @source.has 'scm'
- @requestSCM(@key).done => @sourceView.render()
- else
- @sourceView.render()
-
-
- hideSCM: (store = false) ->
- @settings.set 'scm', false
- @storeSettings() if store
- @sourceView.render()
+ enablePeriod: (period) ->
+ @period = @periods.findWhere key: period
+ @render()
showAllLines: ->
@sourceView.render()
- filterLinesByIssues: ->
- issues = @source.get 'issues'
- @sourceView.resetShowBlocks()
- issues.forEach (issue) =>
- line = issue.line || 0
- @sourceView.addShowBlock line - LINES_AROUND_ISSUE, line + LINES_AROUND_ISSUE
- @sourceView.render()
-
-
- filterByIssues: (predicate, requestIssues = true) ->
- if requestIssues && !@requestIssuesOnce
- @requestIssues(@key).done => @_filterByIssues(predicate)
- else
- @_filterByIssues(predicate)
-
-
- _filterByIssues: (predicate) ->
- issues = @source.get 'issues'
- @settings.set 'issues', true
- @sourceView.resetShowBlocks()
- activeIssues = []
- issues.forEach (issue) =>
- if predicate issue
- line = issue.line || 0
- @sourceView.addShowBlock line - LINES_AROUND_ISSUE, line + LINES_AROUND_ISSUE
- activeIssues.push issue
- @source.set 'activeIssues', activeIssues
- @sourceView.render()
-
-
- # Current Issue
- filterByCurrentIssue: -> @filterByIssues ((issue) => issue.key == @currentIssue), false
-
- # All Issues
- filterByAllIssues: -> @filterByIssues -> true
-
- # Resolved Issues
- filterByFixedIssues: -> @filterByIssues (issue) -> issue.resolution == 'FIXED'
-
- # Unresolved Issues
- filterByUnresolvedIssues: -> @filterByIssues (issue) -> !issue.resolution
-
- # False Positive
- filterByFalsePositiveIssues: -> @filterByIssues (issue) -> issue.resolution == 'FALSE-POSITIVE'
-
- # Rule
- filterByRule: (rule) -> @filterByIssues (issue) -> issue.rule == rule && !issue.resolution
-
- # Severity
- filterByBlockerIssues: -> @filterByIssues (issue) -> issue.severity == 'BLOCKER' && !issue.resolution
- filterByCriticalIssues: -> @filterByIssues (issue) -> issue.severity == 'CRITICAL' && !issue.resolution
- filterByMajorIssues: -> @filterByIssues (issue) -> issue.severity == 'MAJOR' && !issue.resolution
- filterByMinorIssues: -> @filterByIssues (issue) -> issue.severity == 'MINOR' && !issue.resolution
- filterByInfoIssues: -> @filterByIssues (issue) -> issue.severity == 'INFO' && !issue.resolution
-
-
- filterByCoverage: (predicate) ->
- @requestCoverage(@key).done => @_filterByCoverage(predicate)
-
-
- filterByCoverageIT: (predicate) ->
- @requestCoverage(@key, 'IT').done => @_filterByCoverage(predicate)
-
-
- _filterByCoverage: (predicate) ->
- coverage = @source.get 'coverage'
- @settings.set 'coverage', true
- @sourceView.resetShowBlocks()
- coverage.forEach (c) =>
- if predicate c
- line = c[0]
- @sourceView.addShowBlock line - LINES_AROUND_COVERED_LINE, line + LINES_AROUND_COVERED_LINE
- @sourceView.render()
-
-
- # Unit Tests
- filterByLinesToCover: -> @filterByCoverage (c) -> c[1]?
- filterByCoveredLines: -> @filterByCoverage (c) -> c[1]? && c[1]
- filterByUncoveredLines: -> @filterByCoverage (c) -> c[1]? && !c[1]
- filterByBranchesToCover: -> @filterByCoverage (c) -> c[3]?
- filterByCoveredBranches: -> @filterByCoverage (c) -> c[3]? && c[4]? && (c[4] > 0)
- filterByUncoveredBranches: -> @filterByCoverage (c) -> c[3]? && c[4]? && (c[3] > c[4])
-
- # Integration Tests
- filterByLinesToCoverIT: -> @filterByCoverageIT (c) -> c[1]?
- filterByCoveredLinesIT: -> @filterByCoverageIT (c) -> c[1]? && c[1]
- filterByUncoveredLinesIT: -> @filterByCoverageIT (c) -> c[1]? && !c[1]
- filterByBranchesToCoverIT: -> @filterByCoverageIT (c) -> c[3]?
- filterByCoveredBranchesIT: -> @filterByCoverageIT (c) -> c[3]? && c[4]? && (c[4] > 0)
- filterByUncoveredBranchesIT: -> @filterByCoverageIT (c) -> c[3]? && c[4]? && (c[3] > c[4])
-
-
- # Duplications
- filterByDuplications: ->
- unless @source.has 'duplications'
- @requestDuplications(@key).done => @_filterByDuplications()
- else
- @_filterByDuplications()
-
-
- _filterByDuplications: ->
- duplications = @source.get 'duplications'
- @settings.set 'duplications', true
- @sourceView.resetShowBlocks()
- duplications.forEach (d) =>
- d.blocks.forEach (b) =>
- if b._ref == '1'
- lineFrom = b.from
- lineTo = b.from + b.size
- @sourceView.addShowBlock lineFrom - LINES_AROUND_DUPLICATION, lineTo + LINES_AROUND_DUPLICATION
- @sourceView.render()
-
-
addTransition: (transition, options) ->
@workspace.add
key: @component.get 'key'
--- /dev/null
+define [], () ->
+
+ $ = jQuery
+ API_COVERAGE = "#{baseUrl}/api/coverage/show"
+ LINES_AROUND_COVERED_LINE = 1
+
+
+ class CoverageMixin
+
+ requestCoverage: (key, type = 'UT') ->
+ $.get API_COVERAGE, key: key, type: type, (data) =>
+ @state.set 'hasCoverage', true
+ @source.set coverage: data.coverage
+
+
+ showCoverage: (store = false) ->
+ @settings.set 'coverage', true
+ @storeSettings() if store
+ unless @state.get 'hasCoverage'
+ @requestCoverage(@key).done => @sourceView.render()
+ else
+ @sourceView.render()
+
+
+ hideCoverage: (store = false) ->
+ @settings.set 'coverage', false
+ @storeSettings() if store
+ @sourceView.render()
+
+
+ filterByCoverage: (predicate) ->
+ @requestCoverage(@key).done => @_filterByCoverage(predicate)
+
+
+ filterByCoverageIT: (predicate) ->
+ @requestCoverage(@key, 'IT').done => @_filterByCoverage(predicate)
+
+
+ _filterByCoverage: (predicate) ->
+ coverage = @source.get 'coverage'
+ @settings.set 'coverage', true
+ @sourceView.resetShowBlocks()
+ coverage.forEach (c) =>
+ if predicate c
+ line = c[0]
+ @sourceView.addShowBlock line - LINES_AROUND_COVERED_LINE, line + LINES_AROUND_COVERED_LINE
+ @sourceView.render()
+
+
+ # Unit Tests
+ filterByLinesToCover: -> @filterByCoverage (c) -> c[1]?
+ filterByUncoveredLines: -> @filterByCoverage (c) -> c[1]? && !c[1]
+ filterByBranchesToCover: -> @filterByCoverage (c) -> c[3]?
+ filterByUncoveredBranches: -> @filterByCoverage (c) -> c[3]? && c[4]? && (c[3] > c[4])
+
+ # Integration Tests
+ filterByLinesToCoverIT: -> @filterByCoverageIT (c) -> c[1]?
+ filterByUncoveredLinesIT: -> @filterByCoverageIT (c) -> c[1]? && !c[1]
+ filterByBranchesToCoverIT: -> @filterByCoverageIT (c) -> c[3]?
+ filterByUncoveredBranchesIT: -> @filterByCoverageIT (c) -> c[3]? && c[4]? && (c[3] > c[4])
\ No newline at end of file
--- /dev/null
+define [], () ->
+
+ $ = jQuery
+ API_DUPLICATIONS = "#{baseUrl}/api/duplications/show"
+ LINES_AROUND_DUPLICATION = 1
+
+
+ class DuplicationsMixin
+
+ requestDuplications: (key) ->
+ $.get API_DUPLICATIONS, key: key, (data) =>
+ @state.set 'hasDuplications', true
+ @source.set duplications: data.duplications
+ @source.set duplicationFiles: data.files
+
+
+ showDuplications: (store = false) ->
+ @settings.set 'duplications', true
+ @storeSettings() if store
+ unless @state.get 'hasDuplications'
+ @requestDuplications(@key).done => @sourceView.render()
+ else
+ @sourceView.render()
+
+
+ hideDuplications: (store = false) ->
+ @settings.set 'duplications', false
+ @storeSettings() if store
+ @sourceView.render()
+
+
+ # Duplications
+ filterByDuplications: ->
+ unless @state.get 'hasDuplications'
+ @requestDuplications(@key).done => @_filterByDuplications()
+ else
+ @_filterByDuplications()
+
+
+ _filterByDuplications: ->
+ duplications = @source.get 'duplications'
+ @settings.set 'duplications', true
+ @sourceView.resetShowBlocks()
+ duplications.forEach (d) =>
+ d.blocks.forEach (b) =>
+ if b._ref == '1'
+ lineFrom = b.from
+ lineTo = b.from + b.size
+ @sourceView.addShowBlock lineFrom - LINES_AROUND_DUPLICATION, lineTo + LINES_AROUND_DUPLICATION
+ @sourceView.render()
\ No newline at end of file
--- /dev/null
+define [], () ->
+
+ $ = jQuery
+ API_ISSUES = "#{baseUrl}/api/issues/search"
+ LINES_AROUND_ISSUE = 4
+
+
+ class IssuesMixin
+
+ requestIssues: (key) ->
+ options =
+ components: key
+ ps: 10000
+ extra_fields: 'actions,transitions,assigneeName,actionPlanName'
+ $.get API_ISSUES, options, (data) =>
+ @state.set 'hasIssues', true
+ @source.set issues: data.issues
+
+
+ showIssues: (store = false, issue) ->
+ @settings.set 'issues', true
+ @storeSettings() if store
+ if issue?
+ @currentIssue = issue.key
+ @source.set 'issues', [issue]
+ @filterByCurrentIssue()
+ @headerView.render()
+ else
+ @sourceView.render()
+
+
+ hideIssues: (store = false) ->
+ @settings.set 'issues', false
+ @storeSettings() if store
+ @sourceView.render()
+
+
+ filterLinesByIssues: ->
+ issues = @source.get 'issues'
+ @sourceView.resetShowBlocks()
+ issues.forEach (issue) =>
+ line = issue.line || 0
+ @sourceView.addShowBlock line - LINES_AROUND_ISSUE, line + LINES_AROUND_ISSUE
+ @sourceView.render()
+
+
+ filterByIssues: (predicate, requestIssues = true) ->
+ if requestIssues && !@state.get 'hasIssues'
+ @requestIssues(@key).done => @_filterByIssues(predicate)
+ else
+ @_filterByIssues(predicate)
+
+
+ _filterByIssues: (predicate) ->
+ issues = @source.get 'issues'
+ @settings.set 'issues', true
+ @sourceView.resetShowBlocks()
+ activeIssues = []
+ issues.forEach (issue) =>
+ if predicate issue
+ line = issue.line || 0
+ @sourceView.addShowBlock line - LINES_AROUND_ISSUE, line + LINES_AROUND_ISSUE
+ activeIssues.push issue
+ @source.set 'activeIssues', activeIssues
+ @sourceView.render()
+
+
+ # Current Issue
+ filterByCurrentIssue: -> @filterByIssues ((issue) => issue.key == @currentIssue), false
+
+ # All Issues
+ filterByAllIssues: -> @filterByIssues -> true
+
+ # Resolved Issues
+ filterByFixedIssues: -> @filterByIssues (issue) -> issue.resolution == 'FIXED'
+
+ # Unresolved Issues
+ filterByUnresolvedIssues: -> @filterByIssues (issue) -> !issue.resolution
+
+ # False Positive
+ filterByFalsePositiveIssues: -> @filterByIssues (issue) -> issue.resolution == 'FALSE-POSITIVE'
+
+ # Rule
+ filterByRule: (rule) -> @filterByIssues (issue) -> issue.rule == rule && !issue.resolution
+
+ # Severity
+ filterByBlockerIssues: -> @filterByIssues (issue) -> issue.severity == 'BLOCKER' && !issue.resolution
+ filterByCriticalIssues: -> @filterByIssues (issue) -> issue.severity == 'CRITICAL' && !issue.resolution
+ filterByMajorIssues: -> @filterByIssues (issue) -> issue.severity == 'MAJOR' && !issue.resolution
+ filterByMinorIssues: -> @filterByIssues (issue) -> issue.severity == 'MINOR' && !issue.resolution
+ filterByInfoIssues: -> @filterByIssues (issue) -> issue.severity == 'INFO' && !issue.resolution
\ No newline at end of file
--- /dev/null
+define [], () ->
+
+ $ = jQuery
+ API_SCM = "#{baseUrl}/api/sources/scm"
+
+
+ class SCMMixin
+
+ requestSCM: (key) ->
+ $.get API_SCM, key: key, (data) =>
+ @state.set 'hasSCM', true
+ @source.set scm: data.scm
+
+
+ showSCM: (store = false) ->
+ @settings.set 'scm', true
+ @storeSettings() if store
+ unless @state.get 'hasSCM'
+ @requestSCM(@key).done => @sourceView.render()
+ else
+ @sourceView.render()
+
+
+ hideSCM: (store = false) ->
+ @settings.set 'scm', false
+ @storeSettings() if store
+ @sourceView.render()
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone'
+], (
+ Backbone
+) ->
+
+
+ class Component extends Backbone.Model
\ No newline at end of file
--- /dev/null
+define [
+ 'backbone'
+], (
+ Backbone
+) ->
+
+
+ class Period extends Backbone.Model
+
+ defaults:
+ key: ''
+ label: t 'none'
+ sinceDate: null
--- /dev/null
+define [
+ 'backbone'
+], (
+ Backbone
+) ->
+
+
+ class State extends Backbone.Model
+
+ defaults:
+ hasMeasures: false
+ hasIssues: false
+ hasCoverage: false
+ hasITCoverage: false
+ hasDuplications: false
+ hasTests: false
+ hasSCM: false
+
+ activeHeaderTab: null
\ No newline at end of file
@options.main.showAllLines()
- toggleTimeChangePopup: (e) ->
- e.stopPropagation()
- $('body').click()
- popup = new TimeChangesPopupView
- triggerEl: $(e.currentTarget)
- main: @options.main
- bottom: true
- popup.render()
-
-
augmentWithCoverage: (source) ->
coverage = @model.get 'coverage'
if coverage
class TimeChangesPopupView extends Popup
template: Templates['time-changes-popup']
+
+
+ events:
+ 'click a[data-period]': 'enablePeriod'
+
+
+ enablePeriod: (e) ->
+ period = $(e.currentTarget).data 'period'
+ @options.main.enablePeriod period
+
+
+ serializeData: ->
+ component: @options.main.component.toJSON()
+ periods: @options.main.periods.toJSON()
splitLongName: (longName) ->
lastSeparator = longName.lastIndexOf '/'
dir: longName.substr 0, lastSeparator
- name: longName.substr lastSeparator + 1
\ No newline at end of file
+ name: longName.substr lastSeparator + 1
+
+
+ sortSeverities: (severities) ->
+ order = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO']
+ _.sortBy severities, (s) -> order.indexOf s.key
+
+
+ mixOf: (base, mixins...) ->
+ class Mixed extends base
+ for mixin in mixins by -1 # earlier mixins override later ones
+ for name, method of mixin::
+ Mixed::[name] = method
+ Mixed
\ No newline at end of file
<div class="component-viewer-header-links">
<a><i class="icon-link"></i></a>
- {{#if component.canMarkAsFavourite}}
+ {{#if state.canMarkAsFavourite}}
<a class="js-favorite"
title="{{#if component.fav}}{{t 'click_to_remove_from_favorites'}}{{else}}{{t 'click_to_add_to_favorites'}}{{/if}}">
<i class="{{#if component.fav}}icon-favorite{{else}}icon-not-favorite{{/if}}"></i>
</div>
<div class="component-viewer-header-measures">
- {{#eq component.q 'UTS'}}
+ {{#if component.isUnitTest}}
<div class="component-viewer-header-measures-scope">
<a data-scope="tests" class="component-viewer-header-measures-expand">
<div class="component-viewer-header-measure">
<i class="icon-dropdown"></i>
</a>
</div>
- {{/eq}}
+ {{/if}}
- {{#notEq component.q 'UTS'}}
+ {{#unless component.isUnitTest}}
<div class="component-viewer-header-measures-scope">
<span data-scope="basic" class="js-toggle-coverage component-viewer-header-measures-toggle-scope inactive"></span>
<a data-scope="basic" class="component-viewer-header-measures-expand">
<i class="icon-dropdown"></i>
</a>
</div>
- {{/notEq}}
+ {{/unless}}
<div class="component-viewer-header-measures-scope">
<a data-scope="issues" class="component-viewer-header-measures-expand">
class="js-toggle-issues component-viewer-header-measures-toggle-scope {{#if settings.issues}}active{{/if}}"></a>
</div>
- {{#notEq component.q 'UTS'}}
+ {{#unless component.isUnitTest}}
{{#if component.measures.fCoverage}}
<div class="component-viewer-header-measures-scope">
<a data-scope="coverage" class="component-viewer-header-measures-expand">
class="js-toggle-duplications component-viewer-header-measures-toggle-scope {{#if settings.duplications}}active{{/if}}"></a>
</div>
{{/if}}
- {{/notEq}}
+ {{/unless}}
<div class="component-viewer-header-measures-scope">
<span data-scope="scm" class="component-viewer-header-measures-expand">
class="js-toggle-scm component-viewer-header-measures-toggle-scope {{#if settings.scm}}active{{/if}}"></a>
</div>
</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>
-
-{{#eq component.q 'UTS'}}
- <div data-scope="tests" class="component-viewer-header-expanded-bar">
- {{> '_tests-header'}}
+ <div class="component-viewer-header-time-changes">
+ <a>
+ <i class="icon-period"></i>
+ <div>{{#if period.key}}{{period.label}}{{else}}Time<br>Changes{{/if}}</div>
+ </a>
</div>
-{{/eq}}
-
-
+</div>
-<div class="component-viewer-header-decoration" style="display: none;">
- <div class="button-group">
- <button class="js-toggle-issues {{#if settings.issues}}active{{/if}}">Issues</button>
- <button class="js-toggle-coverage {{#if settings.coverage}}active{{/if}}">Coverage</button>
- <button class="js-toggle-duplications {{#if settings.duplications}}active{{/if}}">Duplications</button>
- <button class="js-toggle-scm {{#if settings.scm}}active{{/if}}">SCM</button>
- </div>
+<div class="component-viewer-header-expanded-bar">
+ <i class="spinner spinner-margin"></i>
</div>
\ No newline at end of file
+++ /dev/null
-{{#with component.msr}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.size'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{{componentViewerHeaderItem lines 'lines'}}}
- {{{componentViewerHeaderItem ncloc 'ncloc'}}}
- </ul>
- </div>
-
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.complexity'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{{componentViewerHeaderItem complexity 'complexity'}}}
- {{{componentViewerHeaderItem function_complexity 'function_complexity'}}}
- </ul>
- </div>
-
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.structure'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{{componentViewerHeaderItem classes 'classes'}}}
- {{{componentViewerHeaderItem functions 'functions'}}}
- {{{componentViewerHeaderItem accessors 'accessors'}}}
- {{{componentViewerHeaderItem statements 'statements'}}}
- </ul>
- </div>
-
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.documentation'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{{componentViewerHeaderItem comment_lines 'comment_lines'}}}
- {{{componentViewerHeaderItem comment_lines_density 'comment_lines_density'}}}
- {{{componentViewerHeaderItem public_api 'public_api'}}}
- {{{componentViewerHeaderItem public_undocumented_api 'public_undocumented_api'}}}
- {{{componentViewerHeaderItem public_documented_api_density 'public_documented_api_density'}}}
- </ul>
- </div>
-{{/with}}
\ No newline at end of file
+++ /dev/null
-{{#with component.msr}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.unit_tests'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{{componentViewerHeaderItem coverage 'coverage'}}}
- {{{componentViewerHeaderItem line_coverage 'line_coverage'}}}
- {{{componentViewerHeaderLink lines_to_cover 'lines_to_cover' 'js-filter-lines-to-cover'}}}
- {{{componentViewerHeaderLink covered_lines 'covered_lines' 'js-filter-covered-lines'}}}
- {{{componentViewerHeaderLink uncovered_lines 'uncovered_lines' 'js-filter-uncovered-lines'}}}
- </ul>
- </div>
-
- {{#any branch_coverage conditions_to_cover covered_conditions uncovered_conditions}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title"> </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- <li><span class="item"> </span></li>
- {{{componentViewerHeaderItem branch_coverage 'branch_coverage'}}}
- {{{componentViewerHeaderLink conditions_to_cover 'conditions_to_cover' 'js-filter-branches-to-cover'}}}
- {{{componentViewerHeaderLink covered_conditions 'covered_conditions' 'js-filter-covered-branches'}}}
- {{{componentViewerHeaderLink uncovered_conditions 'uncovered_conditions' 'js-filter-uncovered-branches'}}}
- </ul>
- </div>
- {{/any}}
-
-
- {{#any it_coverage it_line_coverage it_lines_to_cover it_covered_lines it_uncovered_lines}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.integration_tests'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{{componentViewerHeaderItem it_coverage 'coverage'}}}
- {{{componentViewerHeaderItem it_line_coverage 'line_coverage'}}}
- {{{componentViewerHeaderLink it_lines_to_cover 'lines_to_cover' 'js-filter-lines-to-cover-it'}}}
- {{{componentViewerHeaderLink it_covered_lines 'covered_lines' 'js-filter-covered-lines-it'}}}
- {{{componentViewerHeaderLink it_uncovered_lines 'uncovered_lines' 'js-filter-uncovered-lines-it'}}}
- </ul>
- </div>
- {{/any}}
-
- {{#any it_branch_coverage it_conditions_to_cover it_covered_conditions it_uncovered_conditions}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title"> </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- <li><span class="item"> </span></li>
- {{{componentViewerHeaderItem it_branch_coverage 'branch_coverage'}}}
- {{{componentViewerHeaderLink it_conditions_to_cover 'conditions_to_cover' 'js-filter-branches-to-cover-it'}}}
- {{{componentViewerHeaderLink it_covered_conditions 'covered_conditions' 'js-filter-covered-branches-it'}}}
- {{{componentViewerHeaderLink it_uncovered_conditions 'uncovered_conditions' 'js-filter-uncovered-branches-it'}}}
- </ul>
- </div>
- {{/any}}
-{{/with}}
\ No newline at end of file
+++ /dev/null
-{{#with component.msr}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">{{t 'duplications'}}</div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{{componentViewerHeaderLink duplicated_blocks 'duplicated_blocks' 'js-filter-duplications'}}}
- {{{componentViewerHeaderLink duplicated_lines 'duplicated_lines' 'js-filter-duplications'}}}
- </ul>
- </div>
-{{/with}}
\ No newline at end of file
+++ /dev/null
-{{#if component.measures.fIssues}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.severities'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{#each component.severities}}
- <li><a class="item js-filter-{{this.[0]}}-issues">
- <span>{{severityIcon this.[0]}} {{t 'severity' this.[0]}}</span>
- <span class="number">{{this.[2]}}</span>
- <i class="icon-chevron-right"></i>
- </a></li>
- {{/each}}
- </ul>
- </div>
-{{/if}}
-
-{{#if component.measures.fIssues}}
- <div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.rules'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{#each component.rules}}
- <li><a class="item js-filter-rule" data-rule="{{this.[0]}}" title="{{this.[1]}}">
- <span>{{this.[1]}}</span>
- <span class="number">{{this.[2]}}</span>
- <i class="icon-chevron-right"></i>
- </a></li>
- {{/each}}
- </ul>
- </div>
-{{/if}}
-
-<div class="component-viewer-header-expanded-bar-section">
- <div class="component-viewer-header-expanded-bar-section-title">
- {{t 'component_viewer.measure_section.issues'}}
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{#if currentIssue}}
- <li><a class="item js-filter-current-issue">
- <span>{{t 'component_viewer.issues.current_issue'}}</span>
- <i class="icon-chevron-right"></i>
- </a></li>
- {{/if}}
- {{#if component.measures.fIssues}}
- <li><a class="item js-filter-unresolved-issues">
- <span>{{t 'component_viewer.issues.unresolved_issues'}}</span>
- <span class="number">{{component.measures.fIssues}}</span>
- <i class="icon-chevron-right"></i>
- </a></li>
- {{/if}}
- {{#if component.measures.fIssues}}
- <li><a class="item js-filter-fixed-issues">
- <span>{{t 'component_viewer.issues.fixed_issues'}}</span>
- <i class="icon-chevron-right"></i>
- </a></li>
- {{/if}}
- <li><a class="item js-filter-false-positive-issues">
- <span>{{t 'component_viewer.issues.false_positive_issues'}}</span>
- <span class="number">{{component.msr.false_positive_issues}}</span>
- <i class="icon-chevron-right"></i>
- </a></li>
- </ul>
-</div>
-
-{{#if component.canBulkChange}}
- <div class="component-viewer-header-expanded-bar-section component-viewer-header-expanded-bar-section-actions">
- <div class="component-viewer-header-expanded-bar-section-title"> </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- <li><a class="link-action js-issues-bulk-change">
- <span><i class="icon-bulk-change"></i> {{t 'bulk_change'}}</span>
- </a></li>
- </ul>
- </div>
-{{/if}}
\ No newline at end of file
+++ /dev/null
-<div class="component-viewer-header-expanded-bar-section large">
- <div class="component-viewer-header-expanded-bar-section-title justify">
- <span class="ib">{{t 'component_viewer.measure_section.unit_tests'}}</span>
- <span class="ib">Covered Lines</span>
- </div>
- <ul class="component-viewer-header-expanded-bar-section-list">
- {{#each component.tests}}
- <li><a class="item js-unit-test" data-name="{{name}}">
- <span class="label">{{testStatusIcon status}} <span class="subtitle">{{durationInMs}}ms</span>
- {{name}}</span>
- {{#eq status 'OK'}}
- <span class="number">{{coveredLines}}</span>
- {{/eq}}
- <i class="icon-chevron-right"></i>
- </a></li>
- {{/each}}
- </ul>
-</div>
\ No newline at end of file
--- /dev/null
+{{#with component.measures}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.size'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{{componentViewerHeaderItem lines 'lines'}}}
+ {{{componentViewerHeaderItem ncloc 'ncloc'}}}
+ </ul>
+ </div>
+
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.complexity'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{{componentViewerHeaderItem complexity 'complexity'}}}
+ {{{componentViewerHeaderItem function_complexity 'function_complexity'}}}
+ </ul>
+ </div>
+
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.structure'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{{componentViewerHeaderItem classes 'classes'}}}
+ {{{componentViewerHeaderItem functions 'functions'}}}
+ {{{componentViewerHeaderItem accessors 'accessors'}}}
+ {{{componentViewerHeaderItem statements 'statements'}}}
+ </ul>
+ </div>
+
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.documentation'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{{componentViewerHeaderItem comment_lines 'comment_lines'}}}
+ {{{componentViewerHeaderItem comment_lines_density 'comment_lines_density'}}}
+ {{{componentViewerHeaderItem public_api 'public_api'}}}
+ {{{componentViewerHeaderItem public_undocumented_api 'public_undocumented_api'}}}
+ {{{componentViewerHeaderItem public_documented_api_density 'public_documented_api_density'}}}
+ </ul>
+ </div>
+{{/with}}
\ No newline at end of file
--- /dev/null
+{{#with component.measures}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.unit_tests'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{{componentViewerHeaderItem coverage 'coverage'}}}
+ {{{componentViewerHeaderItem line_coverage 'line_coverage'}}}
+ {{{componentViewerHeaderLink lines_to_cover 'lines_to_cover' 'js-filter-lines-to-cover'}}}
+ {{{componentViewerHeaderLink uncovered_lines 'uncovered_lines' 'js-filter-uncovered-lines'}}}
+ </ul>
+ </div>
+
+ {{#any branch_coverage conditions_to_cover covered_conditions uncovered_conditions}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title"> </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><span class="item"> </span></li>
+ {{{componentViewerHeaderItem branch_coverage 'branch_coverage'}}}
+ {{{componentViewerHeaderLink conditions_to_cover 'conditions_to_cover' 'js-filter-branches-to-cover'}}}
+ {{{componentViewerHeaderLink uncovered_conditions 'uncovered_conditions' 'js-filter-uncovered-branches'}}}
+ </ul>
+ </div>
+ {{/any}}
+
+
+ {{#any it_coverage it_line_coverage it_lines_to_cover it_covered_lines it_uncovered_lines}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.integration_tests'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{{componentViewerHeaderItem it_coverage 'coverage'}}}
+ {{{componentViewerHeaderItem it_line_coverage 'line_coverage'}}}
+ {{{componentViewerHeaderLink it_lines_to_cover 'lines_to_cover' 'js-filter-lines-to-cover-it'}}}
+ {{{componentViewerHeaderLink it_uncovered_lines 'uncovered_lines' 'js-filter-uncovered-lines-it'}}}
+ </ul>
+ </div>
+ {{/any}}
+
+ {{#any it_branch_coverage it_conditions_to_cover it_covered_conditions it_uncovered_conditions}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title"> </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><span class="item"> </span></li>
+ {{{componentViewerHeaderItem it_branch_coverage 'branch_coverage'}}}
+ {{{componentViewerHeaderLink it_conditions_to_cover 'conditions_to_cover' 'js-filter-branches-to-cover-it'}}}
+ {{{componentViewerHeaderLink it_uncovered_conditions 'uncovered_conditions' 'js-filter-uncovered-branches-it'}}}
+ </ul>
+ </div>
+ {{/any}}
+{{/with}}
\ No newline at end of file
--- /dev/null
+{{#with component.measures}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">{{t 'duplications'}}</div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{{componentViewerHeaderLink duplicated_blocks 'duplicated_blocks' 'js-filter-duplications'}}}
+ {{{componentViewerHeaderItem duplicated_lines 'duplicated_lines'}}}
+ </ul>
+ </div>
+{{/with}}
\ No newline at end of file
--- /dev/null
+{{#if component.measures.fIssues}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.severities'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{#each state.severities}}
+ <li><a class="item js-filter-{{key}}-issues">
+ <span>{{severityIcon key}} {{name}}</span>
+ <span class="number">{{count}}</span>
+ <i class="icon-chevron-right"></i>
+ </a></li>
+ {{/each}}
+ </ul>
+ </div>
+{{/if}}
+
+{{#if component.measures.fIssues}}
+ <div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.rules'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{#each state.rules}}
+ <li><a class="item js-filter-rule" data-rule="{{key}}" title="{{name}}">
+ <span>{{name}}</span>
+ <span class="number">{{count}}</span>
+ <i class="icon-chevron-right"></i>
+ </a></li>
+ {{/each}}
+ </ul>
+ </div>
+{{/if}}
+
+<div class="component-viewer-header-expanded-bar-section">
+ <div class="component-viewer-header-expanded-bar-section-title">
+ {{t 'component_viewer.measure_section.issues'}}
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{#if currentIssue}}
+ <li><a class="item js-filter-current-issue">
+ <span>{{t 'component_viewer.issues.current_issue'}}</span>
+ <i class="icon-chevron-right"></i>
+ </a></li>
+ {{/if}}
+ {{#if component.measures.fIssues}}
+ <li><a class="item js-filter-unresolved-issues">
+ <span>{{t 'component_viewer.issues.unresolved_issues'}}</span>
+ <span class="number">{{component.measures.fIssues}}</span>
+ <i class="icon-chevron-right"></i>
+ </a></li>
+ {{/if}}
+ {{#if component.measures.fIssues}}
+ <li><a class="item js-filter-fixed-issues">
+ <span>{{t 'component_viewer.issues.fixed_issues'}}</span>
+ <i class="icon-chevron-right"></i>
+ </a></li>
+ {{/if}}
+ <li><a class="item js-filter-false-positive-issues">
+ <span>{{t 'component_viewer.issues.false_positive_issues'}}</span>
+ <span class="number">{{component.measures.false_positive_issues}}</span>
+ <i class="icon-chevron-right"></i>
+ </a></li>
+ </ul>
+</div>
+
+{{#if state.canBulkChange}}
+ <div class="component-viewer-header-expanded-bar-section component-viewer-header-expanded-bar-section-actions">
+ <div class="component-viewer-header-expanded-bar-section-title"> </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ <li><a class="link-action js-issues-bulk-change">
+ <span><i class="icon-bulk-change"></i> {{t 'bulk_change'}}</span>
+ </a></li>
+ </ul>
+ </div>
+{{/if}}
\ No newline at end of file
--- /dev/null
+<div class="component-viewer-header-expanded-bar-section large">
+ <div class="component-viewer-header-expanded-bar-section-title justify">
+ <span class="ib">{{t 'component_viewer.measure_section.unit_tests'}}</span>
+ <span class="ib">Covered Lines</span>
+ </div>
+ <ul class="component-viewer-header-expanded-bar-section-list">
+ {{#each component.tests}}
+ <li><a class="item js-unit-test" data-name="{{name}}">
+ <span class="label">{{testStatusIcon status}} <span class="subtitle">{{durationInMs}}ms</span>
+ {{name}}</span>
+ {{#eq status 'OK'}}
+ <span class="number">{{coveredLines}}</span>
+ {{/eq}}
+ <i class="icon-chevron-right"></i>
+ </a></li>
+ {{/each}}
+ </ul>
+</div>
\ No newline at end of file
-<div class="component-viewer-popup-section">
- <div class="component-viewer-popup-section-title">
- Time changes
- </div>
- <ul class="component-viewer-popup-list">
- <li><a><span>Current</span></a></li>
- <li><a><span>Δ since previous analysis (Apr 02 2014)</span></a></li>
- <li><a><span>Δ over 365 days (Apr 02 2013)</span></a></li>
- <li><a><span>Δ since previous version (4.2 - Feb 24 2014)</span></a></li>
- </ul>
-</div>
+<div class="component-viewer-popup-title">Time Changes</div>
+
+<ul class="component-viewer-popup-list">
+ {{#each periods}}
+ <li><a class="link-action" data-period="{{key}}">{{label}}</a></li>
+ {{/each}}
+</ul>
<div class="component-viewer-popup-arrow"></div>
\ No newline at end of file
& > a { display: block; }
}
+.component-viewer-header-time-changes {
+ float: right;
+ max-width: 180px;
+
+ & > a {
+ display: block;
+ padding: 14px 10px;
+ border-right: 1px solid @barBorderColor;
+ font-size: @smallFontSize;
+ .trans;
+
+ &:hover { background-color: @barBorderColor; }
+
+ & > i {
+ display: block;
+ float: left;
+ margin-top: 8px;
+ margin-right: 4px;
+ }
+
+ & > div {
+ padding: 2px 0;
+ overflow: hidden;
+ }
+ }
+}
+
.component-viewer-header-expanded-bar {
display: none;
.clearfix;
border: 1px solid @barBorderColor;
border-top: none;
background-color: #fff;
+
+ &.active { display: block; }
}
.component-viewer-header-expanded-bar-section {
.component-viewer-popup-list {
margin-top: 5px;
+
+ & > li { padding: 2px 0; }
}
.component-viewer-popup-test {
.component-viewer-popup-test-status {
position: absolute;
- top: 0; left: 0
+ left: 0;
+ top: 50%;
+ margin-top: -8px;
}
.component-viewer-popup-test-duration {
.rotate(240deg);
}
+.spinner-margin {
+ margin: 10px;
+}
+
@-webkit-keyframes spin {
from { .rotate(0deg); }
to { .rotate(360deg); }
-ms-transform: rotate(@degrees);
transform: rotate(@degrees);
}
+.rotateX(@degrees) {
+ -webkit-transform: rotateX(@degrees);
+ -ms-transform: rotateX(@degrees);
+ transform: rotateX(@degrees);
+}
.scale(@ratio) {
-webkit-transform: scale(@ratio);
-ms-transform: scale(@ratio);