Patch by Takenori TAKAKI. git-svn-id: https://svn.redmine.org/redmine/trunk@21519 e93f8b46-1217-0410-a6f0-8f06a7374b81tags/5.1.0
@@ -26,19 +26,23 @@ class AdminController < ApplicationController | |||
before_action :require_admin | |||
helper :queries | |||
include QueriesHelper | |||
helper :projects_queries | |||
helper :projects | |||
def index | |||
@no_configuration_data = Redmine::DefaultData::Loader::no_data? | |||
end | |||
def projects | |||
@status = params[:status] || 1 | |||
scope = Project.status(@status).sorted | |||
scope = scope.like(params[:name]) if params[:name].present? | |||
retrieve_query(ProjectQuery, false, :defaults => @default_columns_names) | |||
@query.admin_projects = 1 | |||
scope = @query.results_scope | |||
@project_count = scope.count | |||
@project_pages = Paginator.new @project_count, per_page_option, params['page'] | |||
@projects = scope.limit(@project_pages.per_page).offset(@project_pages.offset).to_a | |||
@entry_count = scope.count | |||
@entry_pages = Paginator.new @entry_count, per_page_option, params['page'] | |||
@projects = scope.limit(@entry_pages.per_page).offset(@entry_pages.offset).to_a | |||
render :action => "projects", :layout => false if request.xhr? | |||
end |
@@ -52,6 +52,7 @@ class QueriesController < ApplicationController | |||
@query.user = User.current | |||
@query.project = @project | |||
@query.build_from_params(params) | |||
render :layout => 'admin' if params[:admin_projects] | |||
end | |||
def create | |||
@@ -62,13 +63,14 @@ class QueriesController < ApplicationController | |||
if @query.save | |||
flash[:notice] = l(:notice_successful_create) | |||
redirect_to_items(:query_id => @query) | |||
redirect_to_items(:query_id => @query, :admin_projects => params[:admin_projects]) | |||
else | |||
render :action => 'new', :layout => !request.xhr? | |||
end | |||
end | |||
def edit | |||
render :layout => 'admin' if params[:admin_projects] | |||
end | |||
def update | |||
@@ -76,7 +78,7 @@ class QueriesController < ApplicationController | |||
if @query.save | |||
flash[:notice] = l(:notice_successful_update) | |||
redirect_to_items(:query_id => @query) | |||
redirect_to_items(:query_id => @query, :admin_projects => params[:admin_projects]) | |||
else | |||
render :action => 'edit' | |||
end | |||
@@ -110,10 +112,15 @@ class QueriesController < ApplicationController | |||
@query ? @query.queried_class.to_s.underscore.pluralize.to_sym : nil | |||
end | |||
def current_menu(project) | |||
super if params[:admin_projects].nil? | |||
end | |||
private | |||
def find_query | |||
@query = Query.find(params[:id]) | |||
@query.admin_projects = params[:admin_projects] if @query.is_a?(ProjectQuery) | |||
@project = @query.project | |||
render_403 unless @query.editable_by?(User.current) | |||
rescue ActiveRecord::RecordNotFound | |||
@@ -163,7 +170,11 @@ class QueriesController < ApplicationController | |||
end | |||
def redirect_to_project_query(options) | |||
redirect_to projects_path(options) | |||
if params[:admin_projects] | |||
redirect_to admin_projects_path(options) | |||
else | |||
redirect_to projects_path(options) | |||
end | |||
end | |||
# Returns the Query subclass, IssueQuery by default |
@@ -462,6 +462,8 @@ module QueriesHelper | |||
url_params = | |||
if controller_name == 'issues' | |||
{:controller => 'issues', :action => 'index', :project_id => @project} | |||
elsif controller_name == 'admin' && action_name == 'projects' | |||
{:admin_projects => '1'} | |||
else | |||
{} | |||
end |
@@ -18,6 +18,8 @@ | |||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
class ProjectQuery < Query | |||
attr_accessor :admin_projects | |||
self.queried_class = Project | |||
self.view_permission = :search_project | |||
@@ -74,6 +76,12 @@ class ProjectQuery < Query | |||
add_custom_fields_filters(project_custom_fields) | |||
end | |||
def build_from_params(params, defaults={}) | |||
query = super | |||
query.admin_projects = params[:admin_projects] | |||
query | |||
end | |||
def available_columns | |||
return @available_columns if @available_columns | |||
@@ -84,7 +92,27 @@ class ProjectQuery < Query | |||
end | |||
def available_display_types | |||
['board', 'list'] | |||
if self.admin_projects | |||
['list'] | |||
else | |||
['board', 'list'] | |||
end | |||
end | |||
def display_type | |||
if self.admin_projects | |||
'list' | |||
else | |||
super | |||
end | |||
end | |||
def project_statuses_values | |||
values = super | |||
if self.admin_projects | |||
values << [l(:project_status_archived), Project::STATUS_ARCHIVED.to_s] | |||
end | |||
values | |||
end | |||
def default_columns_names | |||
@@ -100,7 +128,11 @@ class ProjectQuery < Query | |||
end | |||
def base_scope | |||
Project.visible.where(statement) | |||
if self.admin_projects | |||
Project.where(statement) | |||
else | |||
Project.visible.where(statement) | |||
end | |||
end | |||
def results_scope(options={}) |
@@ -2,47 +2,21 @@ | |||
<%= link_to l(:label_project_new), new_project_path, :class => 'icon icon-add' %> | |||
</div> | |||
<%= title l(:label_project_plural) %> | |||
<h2><%= @query.new_record? ? l(:label_project_plural) : @query.name %></h2> | |||
<%= form_tag({}, :method => :get) do %> | |||
<fieldset><legend><%= l(:label_filter_plural) %></legend> | |||
<label for='status'><%= l(:field_status) %>:</label> | |||
<%= select_tag 'status', project_status_options_for_select(@status), :class => "small", :onchange => "this.form.submit(); return false;" %> | |||
<label for='name'><%= l(:label_project) %>:</label> | |||
<%= text_field_tag 'name', params[:name], :size => 30 %> | |||
<%= submit_tag l(:button_apply), :class => "small", :name => nil %> | |||
<%= link_to l(:button_clear), admin_projects_path, :class => 'icon icon-reload' %> | |||
</fieldset> | |||
<%= form_tag(admin_projects_path(@project, nil), :method => :get, :id => 'query_form') do %> | |||
<%= hidden_field_tag 'admin_projects', '1' %> | |||
<%= render :partial => 'queries/query_form' %> | |||
<% end %> | |||
| |||
<% if @projects.any? %> | |||
<div class="autoscroll"> | |||
<table class="list"> | |||
<thead><tr> | |||
<th><%=l(:label_project)%></th> | |||
<th><%=l(:field_is_public)%></th> | |||
<th><%=l(:field_created_on)%></th> | |||
<th></th> | |||
</tr></thead> | |||
<tbody> | |||
<% project_tree(@projects, :init_level => true) do |project, level| %> | |||
<tr class="<%= project.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>"> | |||
<td class="name"><span><%= link_to_project_settings(project, {}, :title => project.short_description) %></span></td> | |||
<td><%= checked_image project.is_public? %></td> | |||
<td><%= format_date(project.created_on) %></td> | |||
<td class="buttons"> | |||
<%= link_to(l(:button_archive), archive_project_path(project, :status => params[:status]), :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-lock') unless project.archived? %> | |||
<%= link_to(l(:button_unarchive), unarchive_project_path(project, :status => params[:status]), :method => :post, :class => 'icon icon-unlock') if project.archived? %> | |||
<%= link_to(l(:button_copy), copy_project_path(project), :class => 'icon icon-copy') %> | |||
<%= link_to(l(:button_delete), project_path(project), :method => :delete, :class => 'icon icon-del') %> | |||
</td> | |||
</tr> | |||
<% if @query.valid? %> | |||
<%if @projects.any? %> | |||
<%= render :partial => 'projects/list', :locals => { :entries => @projects }%> | |||
<% else %> | |||
<p class="nodata"><%= l(:label_no_data) %></p> | |||
<% end %> | |||
<% end %> | |||
</tbody> | |||
</table> | |||
</div> | |||
<span class="pagination"><%= pagination_links_full @project_pages, @project_count %></span> | |||
<% else %> | |||
<p class="nodata"><%= l(:label_no_data) %></p> | |||
<% content_for :sidebar do %> | |||
<%= render :partial => 'projects/sidebar' %> | |||
<% end %> |
@@ -6,6 +6,9 @@ | |||
<% @query.inline_columns.each do |column| %> | |||
<%= column_header(@query, column) %> | |||
<% end %> | |||
<% if controller_name == 'admin' && action_name == 'projects' %> | |||
<th></th> | |||
<% end %> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
@@ -23,12 +26,23 @@ | |||
<%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}", | |||
"toggleAllRowGroups(this)", :class => 'toggle-all') %> | |||
</td> | |||
<% if controller_name == 'admin' && action_name == 'projects' %> | |||
<td></td> | |||
<% end %> | |||
</tr> | |||
<% end %> | |||
<tr id="project-<%= entry.id %>" class="<%= cycle('odd', 'even') %> <%= entry.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>"> | |||
<% @query.inline_columns.each do |column| %> | |||
<%= content_tag('td', column_content(column, entry), :class => column.css_classes) %> | |||
<% end %> | |||
<% if controller_name == 'admin' && action_name == 'projects' %> | |||
<td class="buttons"> | |||
<%= link_to(l(:button_archive), archive_project_path(entry, :status => params[:status]), :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-lock') unless entry.archived? %> | |||
<%= link_to(l(:button_unarchive), unarchive_project_path(entry, :status => params[:status]), :method => :post, :class => 'icon icon-unlock') if entry.archived? %> | |||
<%= link_to(l(:button_copy), copy_project_path(entry), :class => 'icon icon-copy') %> | |||
<%= link_to(l(:button_delete), project_path(entry), :method => :delete, :class => 'icon icon-del') %> | |||
</td> | |||
<% end %> | |||
</tr> | |||
<% end -%> | |||
</tbody> |
@@ -4,6 +4,7 @@ | |||
<div class="tabular"> | |||
<%= hidden_field_tag 'gantt', '1' if params[:gantt] %> | |||
<%= hidden_field_tag 'calendar', '1' if params[:calendar] %> | |||
<%= hidden_field_tag 'admin_projects', '1' if params[:admin_projects] %> | |||
<p><label for="query_name"><%=l(:field_name)%></label> | |||
<%= text_field 'query', 'name', :size => 80 %></p> | |||
@@ -34,6 +35,8 @@ | |||
<p><label for='display_type'><%= l(:label_display_type) %></label> | |||
<%= available_display_types_tags(@query) %> | |||
</p> | |||
<% elsif @query.available_display_types.size == 1 %> | |||
<%= hidden_field_tag 'query[display_type]', @query.available_display_types.first %> | |||
<% end %> | |||
<p id ="default_columns"><label for="query_default_columns"><%=l(:label_default_columns)%></label> |
@@ -63,8 +63,9 @@ | |||
<% 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' %> | |||
<%= delete_link query_path(@query), {}, l(:button_delete_object, object_name: l(:label_query).downcase) %> | |||
<% redirect_params = (controller_name == 'admin' && action_name == 'projects') ? {:admin_projects => 1} : {} %> | |||
<%= link_to l(:button_edit_object, object_name: l(:label_query).downcase), edit_query_path(@query, redirect_params), :class => 'icon icon-edit' %> | |||
<%= delete_link query_path(@query, redirect_params), {}, l(:button_delete_object, object_name: l(:label_query).downcase) %> | |||
<% end %> | |||
<% end %> | |||
</p> |
@@ -38,29 +38,43 @@ class AdminControllerTest < Redmine::ControllerTest | |||
assert_select 'div.nodata' | |||
end | |||
def test_projects | |||
def test_projects_should_show_only_active_projects_by_default | |||
p = Project.find(1) | |||
p.update_column :status, 5 | |||
get :projects | |||
assert_response :success | |||
assert_select 'tr.project.closed', 0 | |||
assert_select 'tr.project', 5 | |||
assert_select 'tr.project td.name', :text => 'OnlineStore' | |||
assert_select 'tr.project td.name', :text => p.name, :count => 0 | |||
end | |||
def test_projects_with_status_filter | |||
p = Project.find(1) | |||
p.update_column :status, 5 | |||
get( | |||
:projects, | |||
:params => { | |||
:status => 1 | |||
'set_filter' => '1', | |||
'f' => ['status'], | |||
'op' => {'status' => '='}, | |||
'v' => {'status' => ['5']} | |||
} | |||
) | |||
assert_response :success | |||
assert_select 'tr.project.closed', 0 | |||
assert_select 'tr.project', 1 | |||
assert_select 'tr.project td.name', :text => p.name | |||
end | |||
def test_projects_with_name_filter | |||
get( | |||
:projects, | |||
:params => { | |||
:name => 'store', | |||
:status => '' | |||
'set_filter' => '1', | |||
'f' => ['status', 'name'], | |||
'op' => {'status' => '=', 'name' => '~'}, | |||
'v' => {'status' => ['1'], 'name' => ['store']} | |||
} | |||
) | |||
assert_response :success |
@@ -585,6 +585,33 @@ class QueriesControllerTest < Redmine::ControllerTest | |||
assert q.valid? | |||
end | |||
def test_create_admin_projects_query_should_redirect_to_admin_projects | |||
@request.session[:user_id] = 1 | |||
q = new_record(ProjectQuery) do | |||
post( | |||
:create, | |||
:params => { | |||
:type => 'ProjectQuery', | |||
:default_columns => '1', | |||
:f => ["status"], | |||
:op => { | |||
"status" => "=" | |||
}, | |||
:v => { | |||
"status" => ['1'] | |||
}, | |||
:query => { | |||
"name" => "test_new_project_public_query", "visibility" => "2" | |||
}, | |||
:admin_projects => 1 | |||
} | |||
) | |||
end | |||
assert_redirected_to :controller => 'admin', :action => 'projects', :query_id => q.id, :admin_projects => 1 | |||
end | |||
def test_edit_global_public_query | |||
@request.session[:user_id] = 1 | |||
get(:edit, :params => {:id => 4}) | |||
@@ -690,6 +717,33 @@ class QueriesControllerTest < Redmine::ControllerTest | |||
assert q.valid? | |||
end | |||
def test_update_admin_projects_query | |||
q = ProjectQuery.create(:name => 'project_query') | |||
@request.session[:user_id] = 1 | |||
put( | |||
:update, | |||
:params => { | |||
:id => q.id, | |||
:default_columns => '1', | |||
:fields => ["status"], | |||
:operators => { | |||
"status" => "=" | |||
}, | |||
:values => { | |||
"status" => ['1'] | |||
}, | |||
:query => { | |||
"name" => "test_project_query_updated", "visibility" => "2" | |||
}, | |||
:admin_projects => 1 | |||
} | |||
) | |||
assert_redirected_to :controller => 'admin', :action => 'projects', :query_id => q.id, :admin_projects => 1 | |||
assert Query.find_by_name('test_project_query_updated') | |||
end | |||
def test_update_with_failure | |||
@request.session[:user_id] = 1 | |||
put( |
@@ -62,6 +62,18 @@ class ProjectQueryTest < ActiveSupport::TestCase | |||
assert_include :cf_3, query.available_columns.map(&:name) | |||
end | |||
def test_available_display_types_should_returns_bord_and_list | |||
query = ProjectQuery.new | |||
query.admin_projects = nil | |||
assert_equal ['board', 'list'], query.available_display_types | |||
end | |||
def test_available_display_types_should_always_returns_list_when_admin_projects_is_set | |||
query = ProjectQuery.new | |||
query.admin_projects = 1 | |||
assert_equal ['list'], query.available_display_types | |||
end | |||
def test_display_type_default_should_equal_with_setting_project_list_display_type | |||
ProjectQuery.new.available_display_types.each do |t| | |||
with_settings :project_list_display_type => t do | |||
@@ -104,4 +116,36 @@ class ProjectQueryTest < ActiveSupport::TestCase | |||
assert_nil ProjectQuery.default | |||
end | |||
def test_display_type_should_returns_list_when_admin_projects_is_set | |||
q = ProjectQuery.new | |||
q.admin_projects = 1 | |||
assert_equal 'list', q.display_type | |||
end | |||
def test_project_statuses_values_should_equal_ancestors_return | |||
ancestor = Query.new | |||
q = ProjectQuery.new | |||
assert_equal ancestor.project_statuses_values, q.project_statuses_values | |||
end | |||
def test_project_statuses_values_should_includes_project_status_archeved_when_admin_projects_is_set | |||
q = ProjectQuery.new | |||
q.admin_projects = 1 | |||
assert_includes q.project_statuses_values, [l(:project_status_archived), Project::STATUS_ARCHIVED.to_s] | |||
Query.new.project_statuses_values.each do |status| | |||
assert_includes q.project_statuses_values, status | |||
end | |||
end | |||
def test_base_scope_should_return_visible_projects | |||
q = ProjectQuery.new | |||
assert_equal Project.visible, q.base_scope | |||
end | |||
def test_base_scope_should_return_all_projects_when_admin_projects_is_set | |||
q = ProjectQuery.new | |||
q.admin_projects = 1 | |||
assert_equal Project.all, q.base_scope | |||
end | |||
end |