diff options
author | Julien Lancelot <julien.lancelot@gmail.com> | 2013-06-13 16:19:11 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@gmail.com> | 2013-06-13 16:19:11 +0200 |
commit | a06137eb1111b48e20ccc2f0ac5989e35bd83c55 (patch) | |
tree | e676920c3b554508a58ca8558d9941a561cb0515 /sonar-server | |
parent | 9678ebc554ee2c2581268c956040e3ebc7adcb12 (diff) | |
download | sonarqube-a06137eb1111b48e20ccc2f0ac5989e35bd83c55.tar.gz sonarqube-a06137eb1111b48e20ccc2f0ac5989e35bd83c55.zip |
SONAR-4383 Save issue filter
Diffstat (limited to 'sonar-server')
11 files changed, 323 insertions, 248 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java index e944d5a325b..c8c2967d2f5 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java @@ -280,41 +280,14 @@ public class InternalRubyIssueService implements ServerComponent { String projectParam = parameters.get("project"); Date deadLine = null; - if (Strings.isNullOrEmpty(name)) { - result.addError(Result.Message.ofL10n("errors.cant_be_empty", "name")); - } else { - if (name.length() > 200) { - result.addError(Result.Message.ofL10n("errors.is_too_long", "name", 200)); - } - } - - if (!Strings.isNullOrEmpty(description) && description.length() > 1000) { - result.addError(Result.Message.ofL10n("errors.is_too_long", "description", 1000)); - } + checkMandatorySizeParameter(name, "name", 200, result); + checkOptionnalSizeParameter(description, "description", 1000, result); // Can only set project on creation if (existingActionPlan == null) { - if (Strings.isNullOrEmpty(projectParam)) { - result.addError(Result.Message.ofL10n("errors.cant_be_empty", "project")); - } else { - ResourceDto project = resourceDao.getResource(ResourceQuery.create().setKey(projectParam)); - if (project == null) { - result.addError(Result.Message.ofL10n("action_plans.errors.project_does_not_exist", projectParam)); - } - } - } - - if (!Strings.isNullOrEmpty(deadLineParam)) { - try { - deadLine = RubyUtils.toDate(deadLineParam); - Date today = new Date(); - if (deadLine != null && deadLine.before(today) && !org.apache.commons.lang.time.DateUtils.isSameDay(deadLine, today)) { - result.addError(Result.Message.ofL10n("action_plans.date_cant_be_in_past")); - } - } catch (SonarException e) { - result.addError(Result.Message.ofL10n("errors.is_not_valid", "date")); - } + checkProject(projectParam, result); } + deadLine = checkAndReturnDeadline(deadLineParam, result); if (!Strings.isNullOrEmpty(projectParam) && !Strings.isNullOrEmpty(name) && (existingActionPlan == null || !name.equals(existingActionPlan.name())) && actionPlanService.isNameAlreadyUsedForProject(name, projectParam)) { @@ -339,6 +312,33 @@ public class InternalRubyIssueService implements ServerComponent { return result; } + private void checkProject(String projectParam, Result<ActionPlan> result){ + if (Strings.isNullOrEmpty(projectParam)) { + result.addError(Result.Message.ofL10n("errors.cant_be_empty", "project")); + } else { + ResourceDto project = resourceDao.getResource(ResourceQuery.create().setKey(projectParam)); + if (project == null) { + result.addError(Result.Message.ofL10n("action_plans.errors.project_does_not_exist", projectParam)); + } + } + } + + private Date checkAndReturnDeadline(String deadLineParam, Result<ActionPlan> result){ + Date deadLine = null; + if (!Strings.isNullOrEmpty(deadLineParam)) { + try { + deadLine = RubyUtils.toDate(deadLineParam); + Date today = new Date(); + if (deadLine != null && deadLine.before(today) && !org.apache.commons.lang.time.DateUtils.isSameDay(deadLine, today)) { + result.addError(Result.Message.ofL10n("action_plans.date_cant_be_in_past")); + } + } catch (SonarException e) { + result.addError(Result.Message.ofL10n("errors.is_not_valid", "date")); + } + } + return deadLine; + } + private Result<ActionPlan> createResultForExistingActionPlan(String actionPlanKey) { Result<ActionPlan> result = Result.of(); if (findActionPlan(actionPlanKey) == null) { @@ -369,6 +369,14 @@ public class InternalRubyIssueService implements ServerComponent { return PublicRubyIssueService.toQuery(props); } + public DefaultIssueFilter findIssueFilter(Long id) { + return issueFilterService.findById(id, UserSession.get()); + } + + public DefaultIssueFilter createFilterFromMap(Map<String, Object> mapData) { + return issueFilterService.createEmptyFilter(mapData); + } + /** * Execute issue filter */ @@ -379,29 +387,69 @@ public class InternalRubyIssueService implements ServerComponent { /** * Create issue filter */ - public void createIssueFilter(Map<String, String> params) { + public Result<DefaultIssueFilter> createIssueFilter(Map<String, String> params) { Result<DefaultIssueFilter> result = Result.of(); try { // mandatory parameters String name = params.get("name"); String description = params.get("description"); String data = params.get("data"); + Boolean shared = RubyUtils.toBoolean(params.get("shared")); if (result.ok()) { - DefaultIssueFilter defaultIssueFilter = new DefaultIssueFilter() - .setName(name) + DefaultIssueFilter defaultIssueFilter = DefaultIssueFilter.create(name) .setDescription(description) - .setData(data) - ; - defaultIssueFilter = issueFilterService.create(defaultIssueFilter, UserSession.get()); + .setShared(shared) + .setData(data); + defaultIssueFilter = issueFilterService.save(defaultIssueFilter, UserSession.get()); result.set(defaultIssueFilter); } } catch (Exception e) { result.addError(e.getMessage()); } + return result; + } + @VisibleForTesting + Result<DefaultIssueFilter> createIssueFilterResult(Map<String, String> params) { + Result<DefaultIssueFilter> result = Result.of(); + + // mandatory parameters + String name = params.get("name"); + String description = params.get("description"); + String data = params.get("data"); + Boolean shared = RubyUtils.toBoolean(params.get("shared")); + + checkMandatorySizeParameter(name, "name", 100, result); + checkOptionnalSizeParameter(description, "description", 4000, result); + + // TODO check name uniquness + + if (result.ok()) { + DefaultIssueFilter defaultIssueFilter = DefaultIssueFilter.create(name) + .setDescription(description) + .setShared(shared) + .setData(data); + result.set(defaultIssueFilter); + } + return result; } + private void checkMandatorySizeParameter(String value, String paramName, Integer size, Result result){ + if (Strings.isNullOrEmpty(value)) { + result.addError(Result.Message.ofL10n("errors.cant_be_empty", paramName)); + } else { + if (value.length() > size) { + result.addError(Result.Message.ofL10n("errors.is_too_long", paramName, size)); + } + } + } + + private void checkOptionnalSizeParameter(String value, String paramName, Integer size, Result result){ + if (!Strings.isNullOrEmpty(value) && value.length() > size) { + result.addError(Result.Message.ofL10n("errors.is_too_long", paramName, size)); + } + } }
\ No newline at end of file diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java index d57b32537eb..61dd367abc3 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueFilterService.java @@ -20,10 +20,6 @@ package org.sonar.server.issue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; import org.sonar.api.issue.IssueFinder; import org.sonar.api.issue.IssueQuery; @@ -33,12 +29,9 @@ import org.sonar.core.issue.db.IssueFilterDao; import org.sonar.core.issue.db.IssueFilterDto; import org.sonar.server.user.UserSession; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import javax.annotation.CheckForNull; -import static com.google.common.collect.Lists.newArrayList; -import static com.google.common.collect.Maps.newHashMap; +import java.util.Map; public class IssueFilterService implements ServerComponent { @@ -50,11 +43,32 @@ public class IssueFilterService implements ServerComponent { this.issueFinder = issueFinder; } - public DefaultIssueFilter create(DefaultIssueFilter issueFilter, UserSession userSession) { + @CheckForNull + public DefaultIssueFilter createEmptyFilter(Map<String, Object> mapData) { + return new DefaultIssueFilter(mapData); + } + + @CheckForNull + public DefaultIssueFilter findById(Long id, UserSession userSession) { // TODO // checkAuthorization(userSession, project, UserRole.ADMIN); - issueFilterDao.insert(IssueFilterDto.toIssueFilter(issueFilter)); - return issueFilter; + verifyLoggedIn(userSession); +// access_denied unless filter.shared || filter.owner?(current_user) + + IssueFilterDto issueFilterDto = issueFilterDao.selectById(id); + if (issueFilterDto == null) { + return null; + } + return issueFilterDto.toIssueFilter(); + } + + public DefaultIssueFilter save(DefaultIssueFilter issueFilter, UserSession userSession) { + issueFilter.setUser(userSession.login()); + // TODO +// checkAuthorization(userSession, project, UserRole.ADMIN); + IssueFilterDto issueFilterDto = IssueFilterDto.toIssueFilter(issueFilter); + issueFilterDao.insert(issueFilterDto); + return issueFilterDto.toIssueFilter(); } public DefaultIssueFilter update(DefaultIssueFilter issueFilter, UserSession userSession) { @@ -89,64 +103,11 @@ public class IssueFilterService implements ServerComponent { return null; } - @VisibleForTesting - Map<String, Object> dataAsMap(String data) { - Map<String, Object> map = newHashMap(); - - Iterable<String> keyValues = Splitter.on(DefaultIssueFilter.SEPARATOR).split(data); - for (String keyValue : keyValues) { - String[] keyValueSplit = StringUtils.split(keyValue, DefaultIssueFilter.KEY_VALUE_SEPARATOR); - if (keyValueSplit.length != 2) { - throw new IllegalArgumentException("Key value should be separate by a '"+ DefaultIssueFilter.KEY_VALUE_SEPARATOR + "'"); - } - String key = keyValueSplit[0]; - String value = keyValueSplit[1]; - String[] listValues = StringUtils.split(value, DefaultIssueFilter.LIST_SEPARATOR); - if (listValues.length > 1) { - map.put(key, newArrayList(listValues)); - } else { - map.put(key, value); - } + private void verifyLoggedIn(UserSession userSession) { + if (!userSession.isLoggedIn()) { + // must be logged + throw new IllegalStateException("User is not logged in"); } - return map; - } - - @VisibleForTesting - String mapAsdata(Map<String, Object> map) { - StringBuilder stringBuilder = new StringBuilder(); - - for (Map.Entry<String, Object> entries : map.entrySet()){ - String key = entries.getKey(); - Object value = entries.getValue(); - - stringBuilder.append(key); - stringBuilder.append(DefaultIssueFilter.KEY_VALUE_SEPARATOR); - - List valuesList = newArrayList(); - if (value instanceof List) { - // assume that it contains only strings - valuesList = (List) value; - } else if (value instanceof CharSequence) { - valuesList = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().split((CharSequence) value)); - } else { - stringBuilder.append(value); - } - for (Iterator<Object> valueListIter = valuesList.iterator(); valueListIter.hasNext();) { - Object valueList = valueListIter.next(); - stringBuilder.append(valueList); - if (valueListIter.hasNext()) { - stringBuilder.append(DefaultIssueFilter.LIST_SEPARATOR); - } - } - stringBuilder.append(DefaultIssueFilter.SEPARATOR); - } - - if (stringBuilder.length() > 0) { - // Delete useless last separator character - stringBuilder.deleteCharAt(stringBuilder.length() - 1); - } - - return stringBuilder.toString(); } } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb index da523e067fa..cafdd7f75a7 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb @@ -20,36 +20,120 @@ class IssuesController < ApplicationController - before_filter :init + before_filter :init_options + # GET /issues/index def index redirect_to :action => 'search' end + # GET /issues/search def search - init_results + if params[:id] + @filter = find_filter(params[:id].to_i) + else + @filter = Internal.issues.createFilterFromMap(criteria_params) + end - @criteria_params = params.merge({:controller => nil, :action => nil, :search => nil, :widget_id => nil, :edit => nil}) - @criteria_params['pageSize'] = 100 - @issue_query = Internal.issues.toQuery(@criteria_params) + @issue_query = Internal.issues.toQuery(@filter.dataAsMap) @issues_result = Internal.issues.execute(@issue_query) - @paging = @issues_result.paging - @issues = @issues_result.issues end - private + # Load existing filter + # GET /issues/filter/<filter id> + def filter + require_parameters :id + + @filter = find_filter(params[:id].to_i) + @issue_query = Internal.issues.toQuery(@filter.dataAsMap) + + # criteria can be overridden + # TODO ? + #@filter.override_criteria(criteria_params) + + @issues_result = Internal.issues.execute(@issue_query) + @unchanged = true + render :action => 'search' + end - def init_results - @issues_result = nil - @paging = nil - @issues = nil - #criteria['pageSize'] = 100 - self + # GET /issues/save_as_form?[id=<id>][&criteria] + def save_as_form + if params[:id].present? + @filter = find_filter(params[:id]) + else + @filter = Internal.issues.createFilterFromMap(criteria_params) + end + render :partial => 'issues/save_as_form' end - def init + # POST /issues/save_as?[id=<id>]&name=<name>[¶meters] + def save_as + verify_post_request + access_denied unless logged_in? + + options = {'name' => params[:name], 'description' => params[:description], 'data' => URI.unescape(params[:data]), 'shared' => params[:shared]=='true' } + add_to_favourites=false + if params[:id].present? + # TODO + #@filter = Internal.issues.updateIssueFilter(params[:id], options) + else + filter_result = Internal.issues.createIssueFilter(options) + add_to_favourites=true + end + + if filter_result.ok + @filter = filter_result.get() + puts "#### "+ @filter.id.to_s + #current_user.favourited_measure_filters<<@filter if add_to_favourites + render :text => @filter.id.to_s, :status => 200 + else + @errors = filter_result.errors + render :partial => 'issues/save_as_form', :status => 400 + end + end + + # POST /issues/save?id=<id>&[criteria] + # TODO + def save + verify_post_request + require_parameters :id + access_denied unless logged_in? + + @filter = find_filter(params[:id]) + + #@filter = Internal.issues.updateIssueFilter(params[:id], options) + + #@filter.criteria=criteria_params_without_page_id + #@filter.convert_criteria_to_data + #unless @filter.save + # flash[:error]='Error' + #end + redirect_to :action => 'filter', :id => @filter.id + end + + private + + def init_options @options_for_statuses = Internal.issues.listStatus().map {|s| [message('issue.status.' + s), s]} @options_for_resolutions = Internal.issues.listResolutions().map {|s| [message('issue.resolution.' + s), s]} end + # TODO + def find_filter(id) + filter = Internal.issues.findIssueFilter(id) + # TODO + #access_denied unless filter.shared || filter.owner?(current_user) + filter + end + + def criteria_params + criteria = params + criteria.delete('controller') + criteria.delete('action') + criteria.delete('search') + criteria.delete('edit') + criteria.delete('pageSize') + criteria + end + end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/issue_filter.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/issue_filter.rb deleted file mode 100644 index 09423ffc863..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/issue_filter.rb +++ /dev/null @@ -1,79 +0,0 @@ -# -# Sonar, entreprise quality control tool. -# Copyright (C) 2008-2013 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 3 of the License, or (at your option) any later version. -# -# SonarQube is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -require 'set' -class IssueFilter - - attr_reader :paging, :issues, :issues_result - - def criteria(key=nil) - @criteria ||= HashWithIndifferentAccess.new - if key - @criteria[key] - else - @criteria - end - end - - def criteria=(hash) - @criteria = HashWithIndifferentAccess.new - hash.each_pair do |k, v| - set_criteria_value(k, v) - end - end - - def override_criteria(hash) - @criteria ||= HashWithIndifferentAccess.new - hash.each_pair do |k, v| - set_criteria_value(k, v) - end - end - - # API used by Displays - def set_criteria_value(key, value) - @criteria ||= HashWithIndifferentAccess.new - if key - if value!=nil && value!='' && value!=[''] - value = (value.kind_of?(Array) ? value : value.to_s) - @criteria[key]=value - else - @criteria.delete(key) - end - end - end - - def execute - init_results - @issues_result = Api.issues.find(criteria) - @paging = @issues_result.paging - @issues = @issues_result.issues - self - end - - private - - def init_results - @issues_result = nil - @paging = nil - @issues = nil - criteria['pageSize'] = 100 - self - end - -end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_action_links.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_action_links.html.erb new file mode 100644 index 00000000000..32cfd27c28b --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_action_links.html.erb @@ -0,0 +1,18 @@ +<ul class="operations"> + <% if logged_in? %> + <% if @filter.id %> + <!--TODO--> + <li class="hidden"><a id="copy" href="<%= url_for :action => 'copy_form', :id => @filter.id -%>" class="link-action open-modal"><%= message('copy') -%></a></li> + <% end %> + <% if !defined?(@unchanged) && @filter.id && @filter.user == current_user.login %> + <li> + <%= link_to message('save'), params.merge({:action => 'save', :id => @filter.id}), :class => 'link-action', :id => 'save', :method => :post -%> + </li> + <% end %> + <% unless @filter.id %> + <li> + <a id="save-as" href="<%= url_for params.merge({:action => 'save_as_form', :id => @filter.id}) -%>" class="link-action open-modal"><%= message('save_as') -%></a> + </li> + <% end %> +<% end %> +</ul>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb index 9b93373ad25..6f1e0ba429e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb @@ -18,10 +18,10 @@ <% end %> <% - if @issues && !@issues.empty? + if @issues_result.issues && !@issues_result.issues.empty? colspan = 9 %> - <div> + <div id="issues-list"> <table class="data width100"> <thead> <tr> @@ -59,7 +59,7 @@ </thead> <tbody> <% - @issues.each do |issue| + @issues_result.issues.each do |issue| %> <tr class="<%= cycle('even', 'odd') -%>"> <td width="1%" nowrap> @@ -102,14 +102,14 @@ <% end %> - <% if @issues.empty? %> + <% if @issues_result.issues.empty? %> <tr class="even"> <td colspan="<%= colspan -%>"><%= message 'no_data' -%></td> </tr> <% end %> </tbody> - <%= paginate_java(@paging, :colspan => colspan, :id => 'issue-filter-foot', :include_loading_icon => true) { |label, page_id| + <%= paginate_java(@issues_result.paging, :colspan => colspan, :id => 'issue-filter-foot', :include_loading_icon => true) { |label, page_id| link_to(label, params.merge({:pageIndex => page_id})) } -%> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_save_as_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_save_as_form.html.erb new file mode 100644 index 00000000000..10dcaf7a402 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_save_as_form.html.erb @@ -0,0 +1,40 @@ +<form id="save-as-filter-form" method="post" action="<%= ApplicationController.root_context -%>/issues/save_as"> + <input type="hidden" name="id" value="<%= @filter.id -%>"> + <input type="hidden" name="data" value="<%= u(@filter.data) -%>"> + <fieldset> + <div class="modal-head"> + <h2><%= message('issue_filter.save_filter') -%></h2> + </div> + + <div class="modal-body"> + <% + if @errors + @errors.each do |msg| %> + <div class="error"><%= h (msg.text ? msg.text : Api::Utils.message(msg.l10nKey, :params => msg.l10nParams)) -%></div> + <% end + end + %> + <div class="modal-field"> + <label for="name"><%= message('issue_filter.form.name') -%> <em class="mandatory">*</em></label> + <input id="name" name="name" type="text" size="50" maxlength="100" value="<%= h @filter.name -%>" autofocus="autofocus"/> + </div> + <div class="modal-field"> + <label for="description"><%= message('issue_filter.form.description') -%></label> + <input id="description" name="description" type="text" size="50" maxlength="4000" value="<%= h @filter.description -%>"/> + </div> + <div class="modal-field"> + <label for="shared"><%= message('issue_filter.form.share') -%></label> + <input id="shared" name="shared" type="checkbox" value="true" <%= 'checked' if @filter.shared -%>/> + </div> + </div> + <div class="modal-foot"> + <input type="submit" value="<%= h message('save') -%>" id="save-as-submit"/> + <a href="#" onclick="return closeModalWindow()" id="save-as-cancel"><%= h message('cancel') -%></a> + </div> + </fieldset> +</form> +<script> + $j("#save-as-filter-form").modalForm({success:function (data) { + window.location = baseUrl + '/issues/filter/' + data; + }}); +</script>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_sidebar.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_sidebar.html.erb index dc762c5b1f5..01e6a783115 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_sidebar.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_sidebar.html.erb @@ -1,6 +1,9 @@ <ul class="sidebar gray-sidebar"> <form method="GET" action="<%= ApplicationController.root_context -%>/issues/search" > + <% if @filter.id %> + <input type="hidden" name="id" value="<%= @filter.id.to_s -%>"> + <% end %> <input type="hidden" name="sort" value="<%= @issue_query.sort -%>"/> <input type="hidden" name="asc" value="<%= @issue_query.asc -%>"/> @@ -9,7 +12,7 @@ </li> <li id="criteria-project" class="marginbottom5"> <%= message 'issue_filter.criteria.project' -%>: - <% selected_componentRoot = Internal.component_api.findByKey(@issue_query.componentRoots.get(0)) if @issue_query.componentRoots and @issue_query.componentRoots.size == 1 %> + <% selected_componentRoot = Internal.component_api.findByKey(@issue_query.componentRoots.to_a.first) if @issue_query.componentRoots and @issue_query.componentRoots.size == 1 %> <%= component_select_tag 'componentRoots', :resource_type_property => 'supportsGlobalDashboards', :width => '100%', :selected_resource => selected_componentRoot, :display_key => true, @@ -38,13 +41,13 @@ </li> <li id="criteria-assignee" class="marginbottom5"> <%= message 'issue_filter.criteria.assignee' -%>: - <% selected_assignee = Api.users.findByLogin(@issue_query.assignees.get(0)) if @issue_query.assignees && @issue_query.assignees.size == 1 %> + <% selected_assignee = Api.users.findByLogin(@issue_query.assignees.to_a.first) if @issue_query.assignees && @issue_query.assignees.size == 1 %> <%= user_select_tag('assignees', {:selected_user => selected_assignee, :width => '100%', :placeholder => message('issue_filter.criteria.assignee'), :html_id => 'select-assignee', :open => false, :allow_clear => true}) -%> </li> <li id="criteria-reporter" class="marginbottom5"> <%= message 'issue_filter.criteria.reporter' -%>: - <% selected_reporter = Api.users.findByLogin(@issue_query.reporters.get(0)) if @issue_query.reporters && @issue_query.reporters.size == 1 %> + <% selected_reporter = Api.users.findByLogin(@issue_query.reporters.to_a.first) if @issue_query.reporters && @issue_query.reporters.size == 1 %> <%= user_select_tag('reporters', {:selected_user => selected_reporter, :width => '100%', :placeholder => message('issue_filter.criteria.reporter'), :html_id => 'select-reporter', :open => false, :allow_clear => true}) -%> </li> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb index 1671e29b5da..7ffbc9df5d3 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb @@ -5,12 +5,14 @@ <div class="page-split-right"> <div id="content"> - <div class="marginbottom10"> - <% if @issues_result && @issues_result.maxResultsReached() %> - <p class="notes"><%= message('issue_filter.max_results_reached', :params => @paging.total()) -%></p> - <% end %> - <%= render :partial => 'list' -%> + <div class="line-block marginbottom10"> + <%= render :partial => 'action_links' -%> </div> + + <% if @issues_result && @issues_result.maxResultsReached() %> + <p class="notes"><%= message('issue_filter.max_results_reached', :params => @issues_result.paging.total()) -%></p> + <% end %> + <%= render :partial => 'list' -%> </div> </div> </div>
\ No newline at end of file diff --git a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java index 915b82d82af..eac0c788819 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java @@ -293,4 +293,37 @@ public class InternalRubyIssueServiceTest { assertThat(result).isSameAs(changelog); } + + @Test + public void should_get_error_on_issue_filter_result_when_no_name() { + Map<String, String> parameters = newHashMap(); + parameters.put("name", null); + parameters.put("description", "Long term issues"); + + Result result = service.createIssueFilterResult(parameters); + assertThat(result.ok()).isFalse(); + assertThat(result.errors()).contains(Result.Message.ofL10n("errors.cant_be_empty", "name")); + } + + @Test + public void should_get_error_on_issue_filter_result_when_name_is_too_long() { + Map<String, String> parameters = newHashMap(); + parameters.put("name", createLongString(101)); + parameters.put("description", "Long term issues"); + + Result result = service.createIssueFilterResult(parameters); + assertThat(result.ok()).isFalse(); + assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "name", 100)); + } + + @Test + public void should_get_error_on_issue_filter_result_when_description_is_too_long() { + Map<String, String> parameters = newHashMap(); + parameters.put("name", "Long term"); + parameters.put("description", createLongString(4001)); + + Result result = service.createIssueFilterResult(parameters); + assertThat(result.ok()).isFalse(); + assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "description", 4000)); + } } diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java index 8e00284b13f..6a608f25a47 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueFilterServiceTest.java @@ -21,16 +21,9 @@ package org.sonar.server.issue; import org.junit.Before; -import org.junit.Test; import org.sonar.api.issue.IssueFinder; import org.sonar.core.issue.db.IssueFilterDao; -import java.util.List; -import java.util.Map; - -import static com.google.common.collect.Lists.newArrayList; -import static com.google.common.collect.Maps.newLinkedHashMap; -import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; public class IssueFilterServiceTest { @@ -47,32 +40,4 @@ public class IssueFilterServiceTest { service = new IssueFilterService(issueFilterDao, issueFinder); } - @Test - public void should_convert_data_to_map() { - String data = "issues=ABCDE1234|severities=MAJOR,MINOR|resolved=true|pageSize=10|pageIndex=50"; - - Map<String, Object> map = service.dataAsMap(data); - - assertThat(map).hasSize(5); - assertThat(map.get("issues")).isEqualTo("ABCDE1234"); - assertThat(map.get("severities")).isInstanceOf(List.class); - assertThat((List<String>) map.get("severities")).contains("MAJOR", "MINOR"); - assertThat(map.get("resolved")).isEqualTo("true"); - assertThat(map.get("pageSize")).isEqualTo("10"); - assertThat(map.get("pageIndex")).isEqualTo("50"); - } - - @Test - public void should_convert_map_to_data() { - Map<String, Object> map = newLinkedHashMap(); - map.put("issues", newArrayList("ABCDE1234")); - map.put("severities", newArrayList("MAJOR", "MINOR")); - map.put("resolved", true); - map.put("pageSize", 10l); - map.put("pageIndex", 50); - - String result = service.mapAsdata(map); - - assertThat(result).isEqualTo("issues=ABCDE1234|severities=MAJOR,MINOR|resolved=true|pageSize=10|pageIndex=50"); - } } |