aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2014-07-25 12:18:03 +0200
committerStas Vilchik <vilchiks@gmail.com>2014-07-25 12:18:03 +0200
commit6467547ea541dca0a7d36e001554431d8cfdcd95 (patch)
tree6863e082317fc197da980bbdcbbc4b96b19b508a /server/sonar-web
parent8236c67f081730dc097efe6ce1708eefe4277c34 (diff)
downloadsonarqube-6467547ea541dca0a7d36e001554431d8cfdcd95.tar.gz
sonarqube-6467547ea541dca0a7d36e001554431d8cfdcd95.zip
Revert "Remove unused ruby code"
This reverts commit 1c18af7b7647fef636aaab4bcaecebcd02b7a7ad.
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/issue.js249
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_assign_form.html.erb23
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb26
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_comment_form.html.erb25
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_create_form.html.erb54
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_edit_comment_form.html.erb26
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_error.html.erb6
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb158
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_manual_issue_created.html.erb3
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_plan_form.html.erb37
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_rule.html.erb25
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_severity_form.html.erb19
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb39
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show_modal.html.erb6
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/show.html.erb1
15 files changed, 697 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/issue.js b/server/sonar-web/src/main/js/issue.js
new file mode 100644
index 00000000000..33991b0a00a
--- /dev/null
+++ b/server/sonar-web/src/main/js/issue.js
@@ -0,0 +1,249 @@
+/* Open form for most common actions like comment, assign or plan */
+function issueForm(actionType, elt) {
+ var issueElt = $j(elt).closest('[data-issue-key]');
+ var issueKey = issueElt.attr('data-issue-key');
+ var actionsElt = issueElt.find('.code-issue-actions');
+ var formElt = issueElt.find('.code-issue-form');
+
+ actionsElt.addClass('hidden');
+ formElt.html("<img src='" + baseUrl + "/images/loading-small.gif'>").removeClass('hidden');
+
+ $j.ajax(baseUrl + "/issue/action_form/" + actionType + "?issue=" + issueKey)
+ .done(function (msg) {
+ formElt.html(msg);
+ var focusField = formElt.find('[autofocus]');
+ if (focusField != null) {
+ focusField.focus();
+ }
+ })
+ .fail(function (jqXHR, textStatus) {
+ alert(textStatus);
+ });
+ return false;
+}
+
+/* Close forms opened through the method issueForm() */
+function closeIssueForm(elt) {
+ var issueElt = $j(elt).closest('[data-issue-key]');
+ var actionsElt = issueElt.find('.code-issue-actions');
+ var formElt = issueElt.find('.code-issue-form');
+
+ formElt.addClass('hidden');
+ actionsElt.removeClass('hidden');
+ return false;
+}
+
+/* Raise a Javascript event for Eclipse Web View */
+function notifyIssueChange(issueKey) {
+ $j(document).trigger('sonar.issue.updated', [issueKey]);
+}
+
+/* Submit forms opened through the method issueForm() */
+function submitIssueForm(elt) {
+ var formElt = $j(elt).closest('form');
+ formElt.find('.loading').removeClass('hidden');
+ formElt.find(':submit').prop('disabled', true);
+ var issueElt = formElt.closest('[data-issue-key]');
+ var issueKey = issueElt.attr('data-issue-key');
+
+ $j.ajax({
+ type: "POST",
+ url: baseUrl + '/issue/do_action',
+ data: formElt.serialize()}
+ ).success(function (htmlResponse) {
+ var replaced = $j(htmlResponse);
+ issueElt.replaceWith(replaced);
+ notifyIssueChange(issueKey);
+ }
+ ).fail(function (jqXHR) {
+ closeIssueForm(elt);
+ issueElt.find('.code-issue-actions').replaceWith(jqXHR.responseText);
+ });
+ return false;
+}
+
+function doIssueAction(elt, action, parameters) {
+ var issueElt = $j(elt).closest('[data-issue-key]');
+ var issueKey = issueElt.attr('data-issue-key');
+
+ issueElt.find('.code-issue-actions').html("<img src='" + baseUrl + "/images/loading.gif'>");
+ parameters['issue'] = issueKey;
+
+ $j.ajax({
+ type: "POST",
+ url: baseUrl + '/issue/do_action/' + action,
+ data: parameters
+ }
+ ).success(function (htmlResponse) {
+ var replaced = $j(htmlResponse);
+ issueElt.replaceWith(replaced);
+ notifyIssueChange(issueKey);
+ }
+ ).fail(function (jqXHR) {
+ issueElt.find('.code-issue-actions').replaceWith(jqXHR.responseText);
+ });
+ return false;
+}
+
+// Used for actions defined by plugins
+function doPluginIssueAction(elt, action) {
+ var parameters = {};
+ return doIssueAction(elt, action, parameters);
+}
+
+function assignIssueToMe(elt) {
+ var parameters = {'me': true};
+ return doIssueAction(elt, 'assign', parameters);
+}
+
+function doIssueTransition(elt, transition) {
+ var parameters = {'transition': transition};
+ return doIssueAction(elt, 'transition', parameters);
+}
+
+function deleteIssueComment(elt, confirmMsg) {
+ var commentElt = $j(elt).closest("[data-comment-key]");
+ var commentKey = commentElt.attr('data-comment-key');
+ var issueElt = commentElt.closest('[data-issue-key]');
+ if (confirm(confirmMsg)) {
+ $j.ajax({
+ type: "POST",
+ url: baseUrl + "/issue/delete_comment?id=" + commentKey,
+ success: function (htmlResponse) {
+ issueElt.replaceWith($j(htmlResponse));
+ }
+ });
+ }
+ return false;
+}
+
+function formEditIssueComment(elt) {
+ var commentElt = $j(elt).closest("[data-comment-key]");
+ var commentKey = commentElt.attr('data-comment-key');
+ var issueElt = commentElt.closest('[data-issue-key]');
+
+ issueElt.find('.code-issue-actions').addClass('hidden');
+ commentElt.html("<img src='" + baseUrl + "/images/loading.gif'>");
+
+ $j.get(baseUrl + "/issue/edit_comment_form/" + commentKey, function (html) {
+ commentElt.html(html);
+ });
+ return false;
+}
+
+function doEditIssueComment(elt) {
+ var formElt = $j(elt).closest('form');
+ var issueElt = formElt.closest('[data-issue-key]');
+ var issueKey = issueElt.attr('data-issue-key');
+ $j.ajax({
+ type: "POST",
+ url: baseUrl + "/issue/edit_comment",
+ data: formElt.serialize(),
+ success: function (htmlResponse) {
+ var replaced = $j(htmlResponse);
+ issueElt.replaceWith(replaced);
+ notifyIssueChange(issueKey);
+ },
+ error: function (jqXHR) {
+ closeIssueForm(elt);
+ var commentElt = formElt.closest('[data-comment-key]');
+ commentElt.replaceWith(jqXHR.responseText);
+ }
+ });
+ return false;
+}
+
+function refreshIssue(elt) {
+ var issueElt = $j(elt).closest('[data-issue-key]');
+ var issueKey = issueElt.attr('data-issue-key');
+ $j.get(baseUrl + "/issue/show/" + issueKey + "?only_detail=true", function (html) {
+ var replaced = $j(html);
+ issueElt.replaceWith(replaced);
+ });
+ return false;
+}
+
+/* Open form for creating a manual issue */
+function openCIF(elt, componentId, line) {
+ $j.get(baseUrl + "/issue/create_form?component=" + componentId + "&line=" + line, function (html) {
+ $j(elt).closest('tr').find('td.line').append($j(html));
+ });
+ return false;
+}
+
+/* Close the form used for creating a manual issue */
+function closeCreateIssueForm(elt) {
+ $j(elt).closest('.code-issue-create-form').remove();
+ return false;
+}
+
+/* Create a manual issue */
+function submitCreateIssueForm(elt) {
+ var formElt = $j(elt).closest('form');
+ var loadingElt = formElt.find('.loading');
+
+ loadingElt.removeClass('hidden');
+ $j.ajax({
+ type: "POST",
+ url: baseUrl + '/issue/create',
+ data: formElt.serialize()}
+ ).success(function (html) {
+ var replaced = $j(html);
+ formElt.replaceWith(replaced);
+ }
+ ).error(function (jqXHR) {
+ var errorsElt = formElt.find('.code-issue-errors');
+ errorsElt.html(jqXHR.responseText);
+ errorsElt.removeClass('hidden');
+ }
+ ).always(function () {
+ loadingElt.addClass('hidden');
+ });
+ return false;
+}
+
+function toggleIssueCollapsed(elt) {
+ var issueElt = $j(elt).closest('[data-issue-rule]');
+ issueElt.toggleClass('code-issue-collapsed');
+
+ if (!issueElt.hasClass('code-issue-collapsed')) {
+
+ // Load rule desc
+ // Display loading images and hide existing content
+ var ruleLoading = issueElt.find('.rule-loading');
+ ruleLoading.removeClass('hidden');
+ var ruleElt = issueElt.find('.issue-rule');
+ ruleElt.addClass('hidden');
+ var ruleKey = issueElt.attr('data-issue-rule');
+ $j.get(baseUrl + "/issue/rule/" + ruleKey, function (html) {
+ ruleElt.html(html);
+ // re-enable the links opening modal popups
+ ruleElt.find('.open-modal').modal();
+ }).always(function () {
+ ruleLoading.addClass('hidden');
+ ruleElt.removeClass('hidden');
+ });
+
+ // Load changelog
+ // Display loading images and hide existing content
+ var cangelogLoading = issueElt.find('.changelog-loading');
+ cangelogLoading.removeClass('hidden');
+ var changelogElt = issueElt.find('.issue-changelog');
+ changelogElt.addClass('hidden');
+ var issueKey = issueElt.attr('data-issue-key');
+ $j.get(baseUrl + "/issue/changelog/" + issueKey, function (html) {
+ changelogElt.html(html);
+ }).always(function () {
+ cangelogLoading.addClass('hidden');
+ changelogElt.removeClass('hidden');
+ });
+ }
+ return false;
+}
+
+function openIssuePopup(elt) {
+ var issueElt = $j(elt).closest('[data-issue-key]');
+ var issueKey = issueElt.attr('data-issue-key');
+ openPopup(baseUrl + "/issue/show/" + issueKey + "?layout=false", 'issue');
+ return false;
+}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_assign_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_assign_form.html.erb
new file mode 100644
index 00000000000..e80b3a69106
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_assign_form.html.erb
@@ -0,0 +1,23 @@
+<% user_select_box_id = "assignee-#{params[:issue]}" %>
+<form action="">
+ <input type="hidden" name="issue" value="<%= params[:issue] -%>"/>
+ <input type="hidden" name="id" value="assign"/>
+ <table class="width100">
+ <tr>
+ <td style="vertical-align:top">
+ <%
+ choices = {}
+ choices[current_user.login] = escape_javascript(message('assigned_to_me')) if !@issue.assignee || @issue.assignee != current_user.login
+ choices[''] = escape_javascript(message('unassigned')) if @issue.assignee
+ %>
+ <%=
+ user_select_tag('assignee', :html_id => user_select_box_id, :open => true, :include_choices => choices)
+ -%>
+ <input type="button" value="<%= message('issue.assign.submit') -%>" onclick="submitIssueForm(this)">
+ &nbsp;
+ <%= link_to_function message('cancel'), 'closeIssueForm(this)', :class => 'action' -%>&nbsp;
+ <span class="loading hidden"></span>
+ </td>
+ </tr>
+ </table>
+</form>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb
new file mode 100644
index 00000000000..15827f5df3f
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb
@@ -0,0 +1,26 @@
+<table class="spaced">
+ <tr>
+ <td class="thin left top" nowrap><%= format_datetime(@issue.creationDate()) -%></td>
+ <td class="thin left top"nowrap><%= @issue_results.user(@issue.reporter).name if @issue.reporter -%></td>
+ <td class="left top"><%= message('created') -%></td>
+ </tr>
+ <%
+ @changelog.changes.each do |change|
+ user = @changelog.user(change)
+ %>
+ <tr>
+ <td class="thin left top" nowrap><%= format_datetime(change.creationDate()) -%></td>
+ <td class="thin left top" nowrap><%= h(user.name()) if user -%></td>
+ <td class="left top">
+ <%
+ Internal.issues.formatChangelog(change).each_with_index do |message, index|
+ %>
+ <% if index>0 %><br/><% end %>
+ <%= message -%>
+ <% end %>
+ </td>
+ </tr>
+ <% end %>
+</table>
+
+
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_comment_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_comment_form.html.erb
new file mode 100644
index 00000000000..6b936b5dc37
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_comment_form.html.erb
@@ -0,0 +1,25 @@
+<form action="">
+ <input type="hidden" name="issue" value="<%= params[:issue] -%>"/>
+ <input type="hidden" name="id" value="comment"/>
+ <table class="width100">
+ <tr>
+ <td style="vertical-align:top" colspan="2">
+ <textarea rows="4"
+ name="text"
+ style="width: 100%"
+ autofocus="autofocus"
+ onkeyup="if (this.value == null || this.value=='') $j('#submit-comment').attr('disabled', 'true'); else $j('#submit-comment').attr('disabled', null);"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td style="padding-top: 5px">
+ <input type="submit" value="<%= message('issue.comment.submit') -%>" onclick="return submitIssueForm(this)" id="submit-comment" disabled="disabled"/>
+ &nbsp;<%= link_to_function message('cancel'), 'closeIssueForm(this)' -%>&nbsp;
+ <span class="loading hidden"></span>
+ </td>
+ <td align="right">
+ <%= render :partial => 'markdown/tips' -%>
+ </td>
+ </tr>
+ </table>
+</form> \ No newline at end of file
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_create_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_create_form.html.erb
new file mode 100644
index 00000000000..5ccec3c74ac
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_create_form.html.erb
@@ -0,0 +1,54 @@
+<%
+ manual_rules = Rule.manual_rules
+ is_admin = has_role?(:admin)
+ form_id = "create-issue-#{params[:component]}-#{params[:line]}"
+ rule_select_id = "#{form_id}-rules"
+%>
+<form action="" class="code-issue-create-form" id="<%= form_id -%>">
+ <%
+ if manual_rules.empty?
+ %>
+ <div class="warning" style="margin: 10px">
+
+ <% if is_admin %>
+ <%= message('issue.manual.no_rules.admin') -%>
+ &nbsp;<a href="<%= ApplicationController.root_context -%>/manual_rules/index"><%= message('manage') -%></a>
+ <% else %>
+ <%= message('issue.manual.no_rules.non_admin') -%>
+ <% end %>
+
+ &nbsp;<%= link_to_function message('cancel'), 'closeCreateIssueForm(this)' -%>
+ </div>
+
+ <% else %>
+
+ <input type="hidden" name="line" value="<%= params[:line] -%>"/>
+ <input type="hidden" name="component" value="<%= params[:component] -%>"/>
+
+ <div class="code-issue">
+ <div class="code-issue-name">
+ <%= dropdown_tag 'rule',
+ options_for_select([[]].concat(manual_rules.map { |rule| [rule.name, rule.key] })),
+ {:show_search_box => true, :placeholder => 'Select a Rule'},
+ {:html_id => rule_select_id} -%>
+ </div>
+ <div class="code-issue-msg">
+ <table class="width100">
+ <tr>
+ <td>
+ <textarea rows="4" name="message" class="width100 marginbottom5"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <input type="submit" value="Create" onclick="return submitCreateIssueForm(this);"> &nbsp;
+ <%= link_to_function message('cancel'), 'closeCreateIssueForm(this)' -%> &nbsp;
+ <span class="loading hidden"></span>
+ </td>
+ </tr>
+ </table>
+ <div class="code-issue-errors hidden"></div>
+ </div>
+ </div>
+ <% end %>
+</form>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_edit_comment_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_edit_comment_form.html.erb
new file mode 100644
index 00000000000..11b9871f6c9
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_edit_comment_form.html.erb
@@ -0,0 +1,26 @@
+<form action="">
+ <input type="hidden" name="key" value="<%= @comment.key -%>"/>
+ <table class="width100">
+ <tr>
+ <td style="vertical-align:top" colspan="2">
+ <textarea
+ rows="4"
+ name="text"
+ style="width: 100%"
+ autofocus="autofocus"
+ onkeyup="if (this.value == null || this.value=='') $j('#submit-comment').attr('disabled', 'true'); else $j('#submit-comment').attr('disabled', null);"><%= @comment.markdownText -%></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td style="padding-top: 5px">
+ <input type="submit" value="<%= message('save') -%>"
+ onclick="doEditIssueComment(this);return false" id="submit-comment">
+ &nbsp;<%= link_to_function message('cancel'), 'refreshIssue(this)' -%>&nbsp;
+ <span class="loading hidden"></span>
+ </td>
+ <td align="right">
+ <%= render :partial => 'markdown/tips' -%>
+ </td>
+ </tr>
+ </table>
+</form>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_error.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_error.html.erb
new file mode 100644
index 00000000000..8d52d5e03e3
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_error.html.erb
@@ -0,0 +1,6 @@
+<div class="error">
+ <% @errors.each do |msg| %>
+ <div><%= h (msg.text ? msg.text : Api::Utils.message(msg.l10nKey, :params => msg.l10nParams)) -%></div>
+ <% end %>
+ <%= link_to_function message('hide'), 'refreshIssue(this)' -%>
+</div>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
new file mode 100644
index 00000000000..f83a9992c99
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
@@ -0,0 +1,158 @@
+<div id="issue-<%= u issue.key -%>" class="code-issue code-issue-collapsed" data-issue-key="<%= issue.key -%>" data-issue-component="<%= issue.componentKey() -%>" data-issue-rule="<%= u issue.ruleKey().toString() -%>">
+ <div class="code-issue-name code-issue-toggle">
+ <div class="code-issue-name-rule">
+ <i class="icon-severity-<%= issue.severity.downcase -%>"></i>
+ <span class="rulename">
+ <%= h !issue.message.blank? ? Api::Utils.split_newlines(issue.message).join('<br/>') : @issue_results.rule(issue).getName() -%>
+ </span>
+ </div>
+ <div class="code-issue-permalink">
+ <a href="#" onclick="return openIssuePopup(this)" class="issue-permalink"><img src="<%= ApplicationController.root_context -%>/images/new-window-16.gif"></a>
+ </div>
+ </div>
+
+ <ul class="code-issue-actions code-issue-list">
+ <% if current_user %>
+ <li><a href='#' onclick="return issueForm('comment', this)" class="link-action" autofocus><%= message('issue.comment.formlink') -%></a></li>
+ <% end %>
+ <% unless current_user %>
+ <li>
+ <i class="icon-status-<%= issue.status.downcase -%>"></i><%= message("issue.status.#{issue.status}") -%> <%= '(' + message("issue.resolution.#{issue.resolution}") + ')' if issue.resolution -%>
+ </li>
+ <% else %>
+ <% transitions = Internal.issues.listTransitions(issue).to_a
+ if !transitions.empty? && transitions.first
+ first_transition = transitions.first %>
+ <li>
+ <i class="icon-status-<%= issue.status.downcase -%>"></i><%= message("issue.status.#{issue.status}") -%> <%= '(' + message("issue.resolution.#{issue.resolution}") + ')' if issue.resolution -%>
+ <!-- Display only the first transition -->
+ <a href="#" onclick="return doIssueTransition(this, '<%= first_transition.key -%>')" class="link-action issue-transition spacer-left">
+ <%= message("issue.transition.#{first_transition.key}") -%></a>
+ <!-- Display remaining transitions -->
+ <% if transitions.size > 1 %>
+ <div class="dropdown">
+ <a href="#" class="link-action link-more" onclick="showDropdownMenuOnElement($j(this).next('.dropdown-menu')); return false;"/></a>
+ <ul style="display: none" class="dropdown-menu">
+ <% transitions[1..-1].each do |transition| %>
+ <li>
+ <a href="#" onclick="return doIssueTransition(this, '<%= transition.key -%>')" class="link-action spacer-right"><%= message("issue.transition.#{transition.key}") -%></a>
+ </li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+ </li>
+ <% end %>
+ <% end %>
+ <% unless issue.resolution %>
+ <% if issue.assignee %>
+ <% if current_user %>
+ <li><a href='#' onclick="return issueForm('assign', this)" class="link-action"><%= message('assigned_to') -%></a> <%= h @issue_results.user(issue.assignee).name -%></li>
+ <% else %>
+ <li><%= message('assigned_to') -%> <strong><%= h @issue_results.user(issue.assignee).name -%></strong></li>
+ <% end %>
+ <% elsif current_user %>
+ <li>
+ <a href='#' onclick="return issueForm('assign', this)" class="link-action"><%= message('issue.assign.formlink') -%></a>
+ <% if issue.assignee != current_user.login %>
+ [<a href="#" onclick="return assignIssueToMe(this)" class="link-action"><%= message('issue.assign.to_me') -%></a>]
+ <% end %>
+ </li>
+ <% end %>
+ <% if issue.actionPlanKey %>
+ <% if current_user %>
+ <li><a href="#" onclick="return issueForm('plan', this)" class="link-action"><%= message('issue.planned_for') -%></a> <%= h(@issue_results.actionPlan(issue).name()) -%></li>
+ <% else %>
+ <li><%= message('issue.planned_for') -%> <strong><%= h(@issue_results.actionPlan(issue).name()) -%></strong></li>
+ <% end %>
+ <% elsif current_user %>
+ <li><a href="#" onclick="return issueForm('plan', this)" class="link-action"><%= message('issue.do_plan') -%></a></li>
+ <% end %>
+ <% end %>
+ <% if current_user %>
+ <% plugin_actions = Internal.issues.listActions(issue)
+ if !issue.resolution || !plugin_actions.empty? %>
+ <li>
+ <div class="dropdown">
+ <a href="#" class="link-action link-more" onclick="showDropdownMenuOnElement($j(this).next('.dropdown-menu')); return false;"><%= message('more_actions') -%></a>
+ <ul style="display: none" class="dropdown-menu">
+ <% if Java::OrgSonarServerUser::UserSession.get().hasProjectPermission('issueadmin', issue.projectKey) %>
+ <% unless issue.resolution %>
+ <li>
+ <a href="#" onclick="return issueForm('severity', this)" class="link-action spacer-right"><%= message("issue.set_severity") -%></a>
+ </li>
+ <% end %>
+ <% end %>
+
+ <% # Display actions defined by plugins
+ plugin_actions.each do |action| %>
+ <li>
+ <a href="#" onclick="return doPluginIssueAction(this, '<%= action.key -%>')" class="link-action spacer-right"><%= message("issue.action.#{action.key}.formlink") -%></a>
+ </li>
+ <% end %>
+ </ul>
+ </div>
+ </li>
+ <% end %>
+ <% end %>
+ <% if issue.debt %>
+ <li><%= message('issue.debt') -%>&nbsp;<%= Internal.i18n.formatDuration(issue.debt, 'SHORT') -%></li>
+ <% end %>
+ <% if issue.authorLogin %>
+ <li><%= message('issue.authorLogin') -%>&nbsp;<%= issue.authorLogin -%></li>
+ <% end %>
+ <% if issue.reporter %>
+ <li><%= message('issue.reported_by') -%>&nbsp;<%= @issue_results.user(issue.reporter).name -%></li>
+ <% end %>
+ </ul>
+ <div class="code-issue-form hidden"></div>
+
+ <div class="code-issue-details">
+ <ul class="tabs">
+ <li>
+ <a href="#tab-issue-rule"><%= message('rule') -%></a>
+ </li>
+ <li>
+ <a href="#tab-issue-changelog"><%= message('changelog') -%></a>
+ </li>
+ </ul>
+
+ <div id="tab-issue-rule">
+ <%= image_tag 'loading.gif', :class => 'rule-loading hidden' -%>
+ <div class="issue-rule rule-desc"></div>
+ </div>
+
+ <div id="tab-issue-changelog">
+ <%= image_tag 'loading.gif', :class => 'changelog-loading hidden' -%>
+ <table class="issue-changelog spaced">
+ </table>
+ </div>
+ </div>
+
+ <div class="code-issue-comments">
+ <% issue.comments.each do |comment|
+ comment_html_id = "comment-#{comment.key}-#{rand(100)}" %>
+ <div class="code-issue-comment" id="<%= comment_html_id -%>" data-comment-key="<%= comment.key -%>">
+ <h4>
+ <%= image_tag('reviews/comment.png') -%> &nbsp;<b><%= h( @issue_results.user(comment.userLogin()).name() ) -%></b>
+ (<%= distance_of_time_in_words_to_now(Api::Utils.java_to_ruby_datetime(comment.createdAt)) -%>)
+ <% if current_user && current_user.login==comment.userLogin %>
+ &nbsp;
+ <%= image_tag 'sep12.png' -%>
+ &nbsp;
+ <a class="link-action" href="#" onclick="return formEditIssueComment(this)" ><%= message('edit') -%></a>
+ <a class="link-action spacer-right" href="#" onclick="return deleteIssueComment(this, '<%= escape_javascript(message('issue.comment.delete_confirm_message')) -%>')"><%= message('delete') -%></a>
+ <% end %>
+ </h4>
+ <%= Internal.text.markdownToHtml(comment.markdownText) -%>
+ </div>
+ <% end %>
+ </div>
+</div>
+
+<script>
+ $j('#issue-<%= u issue.key -%> .code-issue-details').tabs();
+ $j('#issue-<%= u issue.key -%> .code-issue-toggle').click(function() {
+ toggleIssueCollapsed(this);
+ });
+</script>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_manual_issue_created.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_manual_issue_created.html.erb
new file mode 100644
index 00000000000..60c05dc18aa
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_manual_issue_created.html.erb
@@ -0,0 +1,3 @@
+<div class="code-issues">
+ <%= render :partial => 'issue/issue', :locals => {:issue => issue} -%>
+</div> \ No newline at end of file
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_plan_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_plan_form.html.erb
new file mode 100644
index 00000000000..802fcf522e1
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_plan_form.html.erb
@@ -0,0 +1,37 @@
+<%
+ plans_select_box_id = "plans-#{params[:issue]}"
+ plans = Internal.issues.findOpenActionPlans(@issue_result.project(@issue).key())
+ if plans.empty?
+%>
+ <% if is_admin? %>
+ <span class="error"><%= message('issue.plan.error.plan_must_be_created_first_for_admin',
+ :params => ApplicationController.root_context + '/action_plans/index/' + @issue_result.project(@issue).key()) -%></span>
+ <% else %>
+ <span class="error"><%= message('issue.plan.error.plan_must_be_created_first_for_other') -%></span>
+ <% end %>
+ &nbsp;<%= link_to_function message('cancel'), 'closeIssueForm(this)' -%>
+<%
+ else
+ first_plan = plans[0]
+ options = plans.map { |plan|
+ label = plan.deadLine ? "#{h plan.name} (#{format_date(plan.deadLine)})" : h(plan.name)
+ [label, plan.key]
+ }
+ if @issue.actionPlanKey
+ options.unshift([escape_javascript(message('issue.unplan.submit')), ''])
+ end
+ plan_options = options_for_select(options, first_plan.key)
+%>
+ <form method="POST">
+ <input type="hidden" name="issue" value="<%= params[:issue] -%>"/>
+ <input type="hidden" id="action-<%= plans_select_box_id %>" name="id" value="plan"/>
+
+ <%= dropdown_tag('plan', plan_options, {:show_search_box => false}, {:id => plans_select_box_id}) -%>
+
+ <input type="button" value="<%= message('issue.plan.submit') -%>" onclick="submitIssueForm(this)">&nbsp;
+ <%= link_to_function message('cancel'), 'closeIssueForm(this)', :class => 'action' -%>
+ <span class="loading hidden"></span>
+
+ </form>
+
+<% end %>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_rule.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_rule.html.erb
new file mode 100644
index 00000000000..588ecab7ef5
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_rule.html.erb
@@ -0,0 +1,25 @@
+<h1 class="marginbottom10"><%= h @rule.name() -%></h1>
+
+<div class="marginbottom10">
+ <% if @rule.htmlDescription.strip.start_with?('<p>') %>
+ <%= Internal.text.interpretMacros(@rule.htmlDescription) %>
+ <% else %>
+ <p><%= Internal.text.interpretMacros(@rule.htmlDescription) %></p>
+ <% end %>
+</div>
+
+<% if @rule.markdownNote() %>
+ <div class="marginbottom10">
+ <%= Api::Utils.markdown_to_html(@rule.markdownNote()) -%>
+ </div>
+<% end %>
+
+<p class="note">
+ <span class="spacer-right"><%= h @rule.key() -%></span>
+ <%= image_tag 'sep12.png', :class => 'spacer-right' -%>
+ <% if @characteristic && @sub_characteristic %>
+ <%= @characteristic.name -%>&nbsp;&gt;&nbsp;<%= @sub_characteristic.name -%>
+ <% else %>
+ <%= message 'issue.technical_debt_deleted' %>
+ <% end %>
+</p>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_severity_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_severity_form.html.erb
new file mode 100644
index 00000000000..9a9ef58e26d
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_severity_form.html.erb
@@ -0,0 +1,19 @@
+<form action="">
+ <input type="hidden" name="issue" value="<%= params[:issue] -%>"/>
+ <input type="hidden" name="id" value="severity"/>
+ <table class="width100">
+ <tr>
+ <td style="vertical-align:top">
+ <select name="severity" class="withIcons" id="severity" autofocus="autofocus">
+ <% Severity::KEYS.each do |severity| %>
+ <option class="sev_<%= severity -%>" value="<%= severity -%>" <%= 'selected' if severity==Severity::MAJOR -%>><%= message("severity.#{severity}") -%></option>
+ <% end %>
+ </select>
+
+ <input type="submit" value="<%= message('issue.set_severity.submit') -%>" onclick="return submitIssueForm(this)">
+ &nbsp;<%= link_to_function message('cancel'), 'closeIssueForm(this)' -%>&nbsp;
+ <span class="loading hidden"></span>
+ </td>
+ </tr>
+ </table>
+</form>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb
new file mode 100644
index 00000000000..acbe92e6e71
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb
@@ -0,0 +1,39 @@
+<div class="issue-detail">
+ <div class="source_title">
+ <%
+ project = @issue_results.project(@issue)
+ component = @issue_results.component(@issue)
+ %>
+
+ <% if project && @issue.componentKey() != project.key() %>
+ <div class="subtitle">
+ <%= h project.longName() -%>
+ </div>
+ <% end %>
+ <span class="h1">
+ <% if component %>
+ <%= qualifier_icon(component) %>
+ <a href="<%= ApplicationController.root_context -%>/component/index#component=<%= component.key() -%>&tab=issues" class="issue-component-link"
+ onclick="window.open(this.href,'resource-<%= component.key().parameterize -%>','height=800,width=900,scrollbars=1,resizable=1');return false;"><%= h component.longName() -%></a>
+ <% else %>
+ <%= h @issue.componentKey() %> [<del><%= message('issue.component_deleted') %></del>]
+ <% end %>
+ </span>
+ </div>
+
+ <div class="marginbottom10">
+ <%= render :partial => 'issue/issue', :locals => {:issue => @issue_results.first} -%>
+ </div>
+
+ <!-- SONAR-4686 Do not display source code if user has not the "Code Viewer" permission -->
+ <% if @snapshot && @issue.line && params[:source]!='false' && has_role?(:codeviewer, @snapshot.project) %>
+ <div class="bordered">
+ <%= snapshot_html_source(@snapshot, {:line_range => (@issue.line-5)..(@issue.line+5), :highlighted_lines => [@issue.line]}) -%>
+ </div>
+ <% else %>
+ <!--
+ SONAR-4438 If no source code, add blank lines in order for the "more action" link to be well displayed
+ -->
+ <div style="height: 60px;"></div>
+ <% end %>
+</div>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show_modal.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show_modal.html.erb
new file mode 100644
index 00000000000..7272b75e9fc
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show_modal.html.erb
@@ -0,0 +1,6 @@
+<div class="modal-body">
+ <%= render :partial => 'issue/show' -%>
+</div>
+<div class="modal-foot">
+ <a href="#" onclick="return closeModalWindow()" autofocus><%= h message('close') -%></a>
+</div> \ No newline at end of file
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/show.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/show.html.erb
new file mode 100644
index 00000000000..8161c09ad7d
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/show.html.erb
@@ -0,0 +1 @@
+<%= render :partial => 'issue/show' -%> \ No newline at end of file