component_viewer.x_lines_are_covered={0} lines are covered
component_viewer.details=Details
+component_viewer.add_manual_issue=Add Manual Issue
+component_viewer.line_actions=Line Actions
component_viewer.workspace=Workspace
component_viewer.workspace.tooltip=Keeps track of history of navigation
--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/component-viewer'
+ 'component-viewer/popup'
+ 'issues/manual-issue-view'
+], (
+ Marionette
+ Templates
+ Popup
+ ManualIssueView
+) ->
+
+ $ = jQuery
+
+
+ class extends Popup
+ template: Templates['line-options-popup']
+
+
+ events:
+ 'click .js-add-manual-issue': 'addManualIssue'
+
+
+ addManualIssue: (e) ->
+ e.preventDefault()
+ line = @options.row.data 'line-number'
+ component = @options.main.component.get 'key'
+ manualIssueView = new ManualIssueView
+ line: line
+ component: component
+ manualIssueView.render().$el.appendTo @options.row.find('.line')
+ manualIssueView.on 'add', (issue) =>
+ issues = @options.main.source.get('issues') || []
+ activeIssues = @options.main.source.get('activeIssues') || []
+ showIssues = @options.main.settings.get 'issues'
+ issues.push issue
+ if showIssues then activeIssues.push issue else activeIssues = [issue]
+ @options.main.source.set 'issues', issues
+ @options.main.source.set 'activeIssues', activeIssues
+ @options.main.settings.set 'issues', true
+ @options.main.sourceView.render()
+
+
'component-viewer/coverage-popup'
'component-viewer/duplication-popup'
'component-viewer/time-changes-popup'
+ 'component-viewer/line-actions-popup'
'issues/issue-view'
'issues/models/issue'
'common/handlebars-extensions'
CoveragePopupView
DuplicationPopupView
TimeChangesPopupView
+ LineActionsPopupView
IssueView
Issue
) ->
@showSettings = false
@renderExpandButtons()
@renderIssues() if @options.main.settings.get('issues') && @model.has('activeIssues')
+ @highlightCurrentLine()
renderExpandButtons: ->
@$el.html '<div style="padding: 10px;"><i class="spinner"></i></div>'
+ showLineActionsPopup: (e) ->
+ e.stopPropagation()
+ $('body').click()
+ popup = new LineActionsPopupView
+ triggerEl: $(e.currentTarget)
+ main: @options.main
+ row: $(e.currentTarget).closest '.row'
+ popup.render()
+
+
highlightLine: (e) ->
@$(".#{HIGHLIGHTED_ROW_CLASS}").removeClass HIGHLIGHTED_ROW_CLASS
- $(e.currentTarget).closest('.row').addClass HIGHLIGHTED_ROW_CLASS
+ row = $(e.currentTarget).closest('.row')
+ row.addClass HIGHLIGHTED_ROW_CLASS
+ @highlightedLine = row.data 'line-number'
+ @showLineActionsPopup(e)
+
+
+ highlightCurrentLine: ->
+ if @highlightedLine?
+ @$("[data-line-number=#{@highlightedLine}]").addClass HIGHLIGHTED_ROW_CLASS
highlightUsages: (e) ->
--- /dev/null
+define [
+ 'backbone.marionette'
+ 'templates/issues'
+], (
+ Marionette
+ Templates
+) ->
+
+ $ = jQuery
+ API_ISSUE = "#{baseUrl}/api/issues/show"
+ API_ADD_MANUAL_ISSUE = "#{baseUrl}/api/issues/create"
+
+
+ class extends Marionette.ItemView
+ template: Templates['manual-issue']
+
+
+ events:
+ 'submit .js-manual-issue-form': 'formSubmit'
+ 'click .js-cancel': 'cancel'
+
+
+ onRender: ->
+ @delegateEvents()
+ @$('[name=rule]').select2
+ width: '250px'
+ minimumResultsForSearch: 10
+
+
+ showSpinner: ->
+ @$('.js-submit').hide()
+ @$('.js-spinner').show()
+
+
+ hideSpinner: ->
+ @$('.js-submit').show()
+ @$('.js-spinner').hide()
+
+
+ validateFields: ->
+ message = @$('[name=message]')
+ unless message.val()
+ message.addClass('invalid').focus()
+ return false
+ return true
+
+
+ formSubmit: (e) ->
+ e.preventDefault()
+ return unless @validateFields()
+ @showSpinner()
+ data = $(e.currentTarget).serialize()
+ $.post API_ADD_MANUAL_ISSUE, data
+ .done (r) =>
+ @addIssue r.issue.key
+ .fail (r) =>
+ @hideSpinner()
+ if r.responseJSON?.errors?
+ @showError _.pluck(r.responseJSON.errors, 'msg').join '. '
+
+
+ addIssue: (key) ->
+ $.get API_ISSUE, key: key, (r) =>
+ @trigger 'add', r.issue
+ @close()
+
+
+ showError: (msg) ->
+ @$('.code-issue-errors').removeClass('hidden').text msg
+
+
+ cancel: ->
+ @close()
+
+
+ serializeData: ->
+ _.extend super,
+ line: @options.line
+ component: @options.component
--- /dev/null
+<div class="component-viewer-popup-container">
+ <div class="component-viewer-popup-title">{{t 'component_viewer.line_actions'}}</div>
+
+ <div class="component-viewer-popup-section">
+ <a href="#" class="js-add-manual-issue link-action">{{t 'component_viewer.add_manual_issue'}}</a>
+ </div>
+</div>
+
+<div class="component-viewer-popup-arrow"></div>
\ No newline at end of file
--- /dev/null
+<form action="" class="js-manual-issue-form code-issue-create-form">
+ {{! no manual rules }}
+ {{! <div class="warning" style="margin: 10px"> }}
+ {{! <% if is_admin %> }}
+ {{! <%= message('issue.manual.no_rules.admin') -%> }}
+ {{! <a href="<%= ApplicationController.root_context -%>/manual_rules/index"><%= message('manage') -%></a> }}
+ {{! <% else %> }}
+ {{! <%= message('issue.manual.no_rules.non_admin') -%> }}
+ {{! <% end %> }}
+ {{! <%= link_to_function message('cancel'), 'closeCreateIssueForm(this)' -%> }}
+ {{! </div> }}
+
+ <input type="hidden" name="line" value="{{line}}">
+ <input type="hidden" name="component" value="{{component}}">
+
+ <div class="code-issue-name">
+ {{! TODO: replace mock data }}
+ <select name="rule">
+ <option value="manual:api">API</option>
+ <option value="manual:design">Design</option>
+ <option value="manual:error_handling">Error handling</option>
+ <option value="manual:performance">Performance</option>
+ <option value="manual:sql_pitfalls">SQL Pitfall</option>
+ </select>
+ </div>
+
+ <div class="code-issue-msg">
+ <table class="width100">
+ <tr>
+ <td>
+ <textarea rows="4" name="message" class="width100 marginbottom5"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td class="js-submit">
+ <input type="submit" value="{{t 'create'}}">
+ <a class="js-cancel" href="#">{{t 'cancel'}}</a>
+ </td>
+ <td class="js-spinner" style="display: none;">
+ <i class="spinner"></i>
+ </td>
+ </tr>
+ </table>
+ <div class="code-issue-errors error hidden"></div>
+ </div>
+
+</form>
td.line { background-color: @barBackgroundColor; }
}
- .code .row-highlighted {
- td.stat { background-color: #e9e94d !important; }
- td.line { background-color: #f1f1a3 !important; }
+ .code .row-highlighted,
+ .code .row-highlighted:hover {
+ td.stat { background-color: #e9e94d; }
+ td.line { background-color: #f1f1a3; }
}
.code td.line {
.code .stat {
&.coverage-green {
- background-color: lighten(@green, 15%);
+ background-color: lighten(@green, 15%) !important;
color: @baseFontColor;
}
&.coverage-orange {
- background-color: lighten(@orange, 15%);
+ background-color: lighten(@orange, 15%) !important;
color: @baseFontColor;
}
&.coverage-red {
- background-color: lighten(@red, 15%);
+ background-color: lighten(@red, 15%) !important;
color: @baseFontColor;
}
}
.component-viewer-popup-section {
width: 450px;
+ padding-bottom: 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: none;
}
+.code-issue-errors {
+ margin-top: 10px;
+}
+
.tab_header {
border-bottom: 1px solid #DDD;
background-color: #EFEFEF;
box-shadow: none;
outline: none;
}
+
+ &.invalid { border-color: @red; }
}
input[type=text],