diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb index 13fa3ade76..1b83f3ee7e 100644 --- a/app/controllers/queries_controller.rb +++ b/app/controllers/queries_controller.rb @@ -20,7 +20,7 @@ class QueriesController < ApplicationController menu_item :issues before_action :find_query, :only => [:edit, :update, :destroy] - before_action :find_optional_project, :only => [:new, :create] + before_action :find_optional_project, :only => [:new, :create, :edit, :update] accept_api_auth :index @@ -121,7 +121,7 @@ class QueriesController < ApplicationController end def update_query_from_params - @query.project = params[:query_is_for_all] ? nil : @project + @query.project = (params[:query] && params[:query][:project_id].present?) ? Project.find(params[:query][:project_id]) : nil @query.build_from_params(params) @query.column_names = nil if params[:default_columns] @query.sort_criteria = (params[:query] && params[:query][:sort_criteria]) || @query.sort_criteria diff --git a/app/views/calendars/show.html.erb b/app/views/calendars/show.html.erb index 76513f50e7..ec39089d58 100644 --- a/app/views/calendars/show.html.erb +++ b/app/views/calendars/show.html.erb @@ -33,7 +33,7 @@ :class => 'icon icon-save' %> <% end %> <% if !@query.new_record? && @query.editable_by?(User.current) %> - <%= link_to l(:button_edit_object, object_name: l(:label_query).downcase), edit_query_path(@query, :calendar => 1), :class => 'icon icon-edit' %> + <%= link_to l(:button_edit_object, object_name: l(:label_query).downcase), edit_query_path(@query, :calendar => 1, :project_id => @project&.identifier), :class => 'icon icon-edit' %> <%= delete_link query_path(@query, :calendar => 1), {}, l(:button_delete_object, object_name: l(:label_query).downcase) %> <% end %>

diff --git a/app/views/gantts/show.html.erb b/app/views/gantts/show.html.erb index e3bfa02ae9..31a3c8d5cd 100644 --- a/app/views/gantts/show.html.erb +++ b/app/views/gantts/show.html.erb @@ -96,7 +96,7 @@ :class => 'icon icon-save' %> <% end %> <% if !@query.new_record? && @query.editable_by?(User.current) %> - <%= link_to l(:button_edit_object, object_name: l(:label_query).downcase), edit_query_path(@query, :gantt => 1), :class => 'icon icon-edit' %> + <%= link_to l(:button_edit_object, object_name: l(:label_query).downcase), edit_query_path(@query, :gantt => 1, :project_id => @project&.identifier), :class => 'icon icon-edit' %> <%= delete_link query_path(@query, :gantt => 1), {}, l(:button_delete_object, object_name: l(:label_query).downcase) %> <% end %>

diff --git a/app/views/queries/_form.html.erb b/app/views/queries/_form.html.erb index 6a94712e01..fec1d9f479 100644 --- a/app/views/queries/_form.html.erb +++ b/app/views/queries/_form.html.erb @@ -24,8 +24,12 @@ <% end %> <% unless @query.type == 'ProjectQuery' %> -

- <%= check_box_tag 'query_is_for_all', 1, @query.project.nil?, :class => (User.current.admin? ? '' : 'disable-unless-private') %>

+

+ <%= radio_button_tag 'query[project_id]', '', @query.project.nil?, id: nil, class: ('disable-unless-private' unless User.current.admin?) %> <%= l(:field_is_for_all) %> + <% if @project %> + <%= radio_button_tag 'query[project_id]', @project.identifier, !@query.project.nil?, id: nil %> <%= @project.name %> + <% end%> +

<% end %> <% unless params[:calendar] %> @@ -105,8 +109,10 @@ $(document).ready(function(){ var roles_checked = $('#query_visibility_1').is(':checked'); var private_checked = $('#query_visibility_0').is(':checked'); $("input[name='query[role_ids][]'][type=checkbox]").attr('disabled', !roles_checked); - if (!private_checked) $("input.disable-unless-private").attr('checked', false); - $("input.disable-unless-private").attr('disabled', !private_checked); + if($("input.disable-unless-private").length){ + if (!private_checked) $("input[name='query[project_id]']:not([value=''])").prop('checked', true); + $("input.disable-unless-private").attr('disabled', !private_checked); + } }).trigger('change'); }); diff --git a/app/views/queries/_query_form.html.erb b/app/views/queries/_query_form.html.erb index 9f1f9ea7e5..0a8ccd8a9d 100644 --- a/app/views/queries/_query_form.html.erb +++ b/app/views/queries/_query_form.html.erb @@ -63,7 +63,7 @@ <% end %> <% else %> <% if @query.editable_by?(User.current) %> - <%= link_to l(:button_edit_object, object_name: l(:label_query).downcase), edit_query_path(@query), :class => 'icon icon-edit' %> + <%= link_to l(:button_edit_object, object_name: l(:label_query).downcase), edit_query_path(@query, project_id: @project&.identifier), :class => 'icon icon-edit' %> <%= delete_link query_path(@query), {}, l(:button_delete_object, object_name: l(:label_query).downcase) %> <% end %> <% end %> diff --git a/app/views/queries/edit.html.erb b/app/views/queries/edit.html.erb index 9db5137c2b..6a9c6df2e2 100644 --- a/app/views/queries/edit.html.erb +++ b/app/views/queries/edit.html.erb @@ -1,6 +1,6 @@

<%= l(:label_query) %>

-<%= form_tag(query_path(@query), :method => :put, :id => "query-form") do %> +<%= form_tag(query_path(@query, project_id: @project&.identifier), :method => :put, :id => "query-form") do %> <%= render :partial => 'form', :locals => {:query => @query} %> <%= submit_tag l(:button_save) %> <% end %> diff --git a/test/functional/queries_controller_test.rb b/test/functional/queries_controller_test.rb index c6b3fec74c..a7d40a1be0 100644 --- a/test/functional/queries_controller_test.rb +++ b/test/functional/queries_controller_test.rb @@ -43,7 +43,10 @@ class QueriesControllerTest < Redmine::ControllerTest assert_response :success assert_select 'input[name=?][value="0"][checked=checked]', 'query[visibility]' - assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked]):not([disabled])' + assert_select 'input[name=?][type=radio]', 'query[project_id]', 2 do + assert_select '[value=""][class="disable-unless-private"]:not([checked])' + assert_select '[value="ecookbook"][checked]' + end assert_select 'select[name=?]', 'c[]' do assert_select 'option[value=tracker]' assert_select 'option[value=subject]' @@ -56,7 +59,9 @@ class QueriesControllerTest < Redmine::ControllerTest assert_response :success assert_select 'input[name=?]', 'query[visibility]', 0 - assert_select 'input[name=query_is_for_all][type=checkbox][checked]:not([disabled])' + assert_select 'input[name=?][type=radio]', 'query[project_id]', 1 do + assert_select '[value=""][class="disable-unless-private"][checked]' + end end def test_new_on_invalid_project @@ -84,6 +89,10 @@ class QueriesControllerTest < Redmine::ControllerTest get(:new, :params => {:project_id => 1, :type => 'TimeEntryQuery'}) assert_response :success assert_select 'input[name=type][value=?]', 'TimeEntryQuery' + assert_select 'input[name=?][type=radio]', 'query[project_id]', 2 do + assert_select '[value=""][class="disable-unless-private"]:not([checked])' + assert_select '[value="ecookbook"][checked]' + end assert_select 'p[class=?]', 'totable_columns', 1 assert_select 'p[class=?]', 'block_columns', 0 end @@ -93,6 +102,7 @@ class QueriesControllerTest < Redmine::ControllerTest get(:new, :params => {:type => 'ProjectQuery'}) assert_response :success assert_select 'input[name=type][value=?]', 'ProjectQuery' + assert_select 'input[name=?]', 'query[project_id]', 0 end def test_new_project_query_should_not_render_roles_visibility_options @@ -104,13 +114,6 @@ class QueriesControllerTest < Redmine::ControllerTest assert_select 'input[id=?]', 'query_visibility_1', 0 end - def test_new_project_query_should_not_render_for_all_projects_option - @request.session[:user_id] = 1 - get(:new, :params => {:type => 'ProjectQuery'}) - assert_response :success - assert_select 'input[name=?]', 'for_all_projects', 0 - end - def test_new_time_entry_query_should_select_spent_time_from_main_menu @request.session[:user_id] = 2 get( @@ -147,6 +150,7 @@ class QueriesControllerTest < Redmine::ControllerTest assert_select 'fieldset#filters' assert_select 'fieldset legend', {:text => 'Sort', :count => 0} assert_select 'fieldset#columns' + assert_select 'input[name=?]', 'query[project_id]' end def test_new_with_calendar_params @@ -159,6 +163,7 @@ class QueriesControllerTest < Redmine::ControllerTest assert_select 'fieldset#filters' assert_select 'fieldset legend', {:text => 'Sort', :count => 0} assert_select 'fieldset#columns', :count => 0 + assert_select 'input[name=?]', 'query[project_id]' end def test_new_without_gantt_and_calendar_params @@ -187,7 +192,7 @@ class QueriesControllerTest < Redmine::ControllerTest "assigned_to_id" => ["1"], "status_id" => ["1"] }, :query => { - "name" => "test_new_project_public_query", "visibility" => "2" + "name" => "test_new_project_public_query", "visibility" => "2", "project_id" => "ecookbook" } } ) @@ -241,7 +246,8 @@ class QueriesControllerTest < Redmine::ControllerTest :query => { "name" => "test_create_project_roles_query", "visibility" => "1", - "role_ids" => ["1", "2", ""] + "role_ids" => ["1", "2", ""], + "project_id" => "ecookbook" } } ) @@ -441,7 +447,7 @@ class QueriesControllerTest < Redmine::ControllerTest :params => { :project_id => 'ecookbook', :query => { - "name" => "name", "visibility" => "2" + "name" => "name", "visibility" => "2", "project_id" => "ecookbook" } } ) @@ -458,9 +464,8 @@ class QueriesControllerTest < Redmine::ControllerTest :create, :params => { :project_id => 'ecookbook', - :query_is_for_all => '1', :query => { - "name" => "name", "visibility" => "2" + "name" => "name", "visibility" => "2", "project_id" => "" } } ) @@ -478,7 +483,7 @@ class QueriesControllerTest < Redmine::ControllerTest :params => { :project_id => 'ecookbook', :query => { - "name" => "name", "visibility" => "2" + "name" => "name", "visibility" => "2", "project_id" => "ecookbook" } } ) @@ -495,9 +500,8 @@ class QueriesControllerTest < Redmine::ControllerTest :create, :params => { :project_id => 'ecookbook', - :query_is_for_all => '1', :query => { - "name" => "name", "visibility" => "2" + "name" => "name", "visibility" => "2", "project_id" => "" } } ) @@ -514,9 +518,8 @@ class QueriesControllerTest < Redmine::ControllerTest :create, :params => { :project_id => 'ecookbook', - :query_is_for_all => '1', :query => { - "name" => "name", "visibility" => "2" + "name" => "name", "visibility" => "2", "project_id" => "" } } ) @@ -544,7 +547,7 @@ class QueriesControllerTest < Redmine::ControllerTest "spent_on" => ["2016-07-14"] }, :query => { - "name" => "test_new_project_public_query", "visibility" => "2" + "name" => "test_new_project_public_query", "visibility" => "2", "project_id" => "ecookbook" } } ) @@ -591,7 +594,9 @@ class QueriesControllerTest < Redmine::ControllerTest assert_response :success assert_select 'input[name=?][value="2"][checked=checked]', 'query[visibility]' - assert_select 'input[name=query_is_for_all][type=checkbox][checked=checked]' + assert_select 'input[name=?][type=radio]', 'query[project_id]', 1 do + assert_select '[value=""][checked]:not([class="disable-unless-private"])' + end end def test_edit_global_private_query @@ -600,25 +605,33 @@ class QueriesControllerTest < Redmine::ControllerTest assert_response :success assert_select 'input[name=?]', 'query[visibility]', 0 - assert_select 'input[name=query_is_for_all][type=checkbox][checked=checked]' + assert_select 'input[name=?][type=radio]', 'query[project_id]', 1 do + assert_select '[value=""][class="disable-unless-private"][checked]' + end end def test_edit_project_private_query @request.session[:user_id] = 3 - get(:edit, :params => {:id => 2}) + get(:edit, :params => {:id => 2, :project_id => 'ecookbook'}) assert_response :success assert_select 'input[name=?]', 'query[visibility]', 0 - assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked])' + assert_select 'input[name=?][type=radio]', 'query[project_id]', 2 do + assert_select '[value=""][class="disable-unless-private"]:not([checked])' + assert_select '[value="ecookbook"][checked]' + end end def test_edit_project_public_query @request.session[:user_id] = 2 - get(:edit, :params => {:id => 1}) + get(:edit, :params => {:id => 1, :project_id => 'ecookbook'}) assert_response :success assert_select 'input[name=?][value="2"][checked=checked]', 'query[visibility]' - assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked])' + assert_select 'input[name=?][type=radio]', 'query[project_id]', 2 do + assert_select '[value=""][class="disable-unless-private"]:not([checked])' + assert_select '[value="ecookbook"][checked]' + end end def test_edit_sort_criteria @@ -653,7 +666,7 @@ class QueriesControllerTest < Redmine::ControllerTest "assigned_to_id" => ["me"], "status_id" => ["1"] }, :query => { - "name" => "test_edit_global_private_query", "visibility" => "2" + "name" => "test_edit_global_private_query", "visibility" => "2", "project_id" => "" } } ) @@ -661,6 +674,7 @@ class QueriesControllerTest < Redmine::ControllerTest q = Query.find_by_name('test_edit_global_private_query') assert !q.is_public? assert q.has_default_columns? + assert_nil q.project assert q.valid? end @@ -679,7 +693,7 @@ class QueriesControllerTest < Redmine::ControllerTest "assigned_to_id" => ["1"], "status_id" => ["1"] }, :query => { - "name" => "test_edit_global_public_query", "visibility" => "2" + "name" => "test_edit_global_public_query", "visibility" => "2", "project_id" => "" } } ) @@ -687,9 +701,48 @@ class QueriesControllerTest < Redmine::ControllerTest q = Query.find_by_name('test_edit_global_public_query') assert q.is_public? assert q.has_default_columns? + assert_nil q.project assert q.valid? end + def test_update_global_private_query_when_change_global_to_project_should_set_project + assert_nil Query.find_by_name('test_edit_global_private_query') + @request.session[:user_id] = 3 + put( + :update, + :params => { + :id => 3, + :project_id => 'ecookbook', + :query => { + "name" => "test_edit_global_private_query", "visibility" => "0", "project_id" => "ecookbook" + } + } + ) + assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => 3 + q = Query.find_by_name('test_edit_global_private_query') + assert !q.is_global? + assert q.project + end + + def test_update_project_private_query_when_change_project_to_global_should_not_set_project + assert_nil Query.find_by_name('test_edit_project_private_query') + @request.session[:user_id] = 3 + put( + :update, + :params => { + :id => 2, + :project_id => 'ecookbook', + :query => { + "name" => "test_edit_project_private_query", "visibility" => "0", "project_id" => "" + } + } + ) + assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => 2 + q = Query.find_by_name('test_edit_project_private_query') + assert q.is_global? + assert_nil q.project + end + def test_update_with_failure @request.session[:user_id] = 1 put(