mirror of
https://github.com/redmine/redmine.git
synced 2025-11-09 23:06:05 +01:00
You can configure default project queries in the following places (#35795):
* App-level: Administration > Projects > Default query (Projects list defaults section) * User-level: My account > Default project query git-svn-id: http://svn.redmine.org/redmine/trunk@21281 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
@@ -51,6 +51,7 @@ class ProjectsController < ApplicationController
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
retrieve_default_query
|
||||||
retrieve_project_query
|
retrieve_project_query
|
||||||
scope = project_scope
|
scope = project_scope
|
||||||
|
|
||||||
@@ -323,4 +324,19 @@ class ProjectsController < ApplicationController
|
|||||||
def retrieve_project_query
|
def retrieve_project_query
|
||||||
retrieve_query(ProjectQuery, false, :defaults => @default_columns_names)
|
retrieve_query(ProjectQuery, false, :defaults => @default_columns_names)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def retrieve_default_query
|
||||||
|
return if params[:query_id].present?
|
||||||
|
return if api_request?
|
||||||
|
return if params[:set_filter] && (params.key?(:op) || params.key?(:f))
|
||||||
|
|
||||||
|
if params[:without_default].present?
|
||||||
|
params[:set_filter] = 1
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if default_query = ProjectQuery.default
|
||||||
|
params[:query_id] = default_query.id
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -170,6 +170,10 @@ module SettingsHelper
|
|||||||
[[l(:label_none), '']] + IssueQuery.only_public.where(project_id: nil).pluck(:name, :id)
|
[[l(:label_none), '']] + IssueQuery.only_public.where(project_id: nil).pluck(:name, :id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def default_global_project_query_options
|
||||||
|
[[l(:label_none), '']] + ProjectQuery.only_public.pluck(:name, :id)
|
||||||
|
end
|
||||||
|
|
||||||
def cross_project_subtasks_options
|
def cross_project_subtasks_options
|
||||||
options = [
|
options = [
|
||||||
[:label_disabled, ''],
|
[:label_disabled, ''],
|
||||||
|
|||||||
@@ -41,6 +41,18 @@ module UsersHelper
|
|||||||
grouped_options_for_select(grouped, user.pref.default_issue_query)
|
grouped_options_for_select(grouped, user.pref.default_issue_query)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def default_project_query_options(user)
|
||||||
|
global_queries = ProjectQuery
|
||||||
|
global_public_queries = global_queries.only_public
|
||||||
|
global_user_queries = global_queries.where(user_id: user.id).where.not(id: global_public_queries.ids)
|
||||||
|
label = user == User.current ? 'label_my_queries' : 'label_default_queries.for_this_user'
|
||||||
|
grouped = {
|
||||||
|
l('label_default_queries.for_all_users') => global_public_queries.pluck(:name, :id),
|
||||||
|
l(".#{label}") => global_user_queries.pluck(:name, :id),
|
||||||
|
}
|
||||||
|
grouped_options_for_select(grouped, user.pref.default_project_query)
|
||||||
|
end
|
||||||
|
|
||||||
def textarea_font_options
|
def textarea_font_options
|
||||||
[[l(:label_font_default), '']] + UserPreference::TEXTAREA_FONT_OPTIONS.map {|o| [l("label_font_#{o}"), o]}
|
[[l(:label_font_default), '']] + UserPreference::TEXTAREA_FONT_OPTIONS.map {|o| [l("label_font_#{o}"), o]}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ class IssueQuery < Query
|
|||||||
|
|
||||||
has_many :projects, foreign_key: 'default_issue_query_id', dependent: :nullify, inverse_of: 'default_issue_query'
|
has_many :projects, foreign_key: 'default_issue_query_id', dependent: :nullify, inverse_of: 'default_issue_query'
|
||||||
after_update { projects.clear unless visibility == VISIBILITY_PUBLIC }
|
after_update { projects.clear unless visibility == VISIBILITY_PUBLIC }
|
||||||
scope :only_public, ->{ where(visibility: VISIBILITY_PUBLIC) }
|
|
||||||
scope :for_all_projects, ->{ where(project_id: nil) }
|
scope :for_all_projects, ->{ where(project_id: nil) }
|
||||||
|
|
||||||
def self.default(project: nil, user: User.current)
|
def self.default(project: nil, user: User.current)
|
||||||
|
|||||||
@@ -37,6 +37,14 @@ class ProjectQuery < Query
|
|||||||
QueryColumn.new(:created_on, :sortable => "#{Project.table_name}.created_on", :default_order => 'desc')
|
QueryColumn.new(:created_on, :sortable => "#{Project.table_name}.created_on", :default_order => 'desc')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def self.default(project: nil, user: User.current)
|
||||||
|
query = nil
|
||||||
|
if user&.logged?
|
||||||
|
query = find_by_id user.pref.default_project_query
|
||||||
|
end
|
||||||
|
query || find_by_id(Setting.default_project_query)
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(attributes=nil, *args)
|
def initialize(attributes=nil, *args)
|
||||||
super attributes
|
super attributes
|
||||||
self.filters ||= {'status' => {:operator => "=", :values => ['1']}}
|
self.filters ||= {'status' => {:operator => "=", :values => ['1']}}
|
||||||
|
|||||||
@@ -339,6 +339,7 @@ class Query < ActiveRecord::Base
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
scope :sorted, lambda {order(:name, :id)}
|
scope :sorted, lambda {order(:name, :id)}
|
||||||
|
scope :only_public, ->{ where(visibility: VISIBILITY_PUBLIC) }
|
||||||
|
|
||||||
# to be implemented in subclasses that have a way to determine a default
|
# to be implemented in subclasses that have a way to determine a default
|
||||||
# query for the given options
|
# query for the given options
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class UserPreference < ActiveRecord::Base
|
|||||||
'recently_used_projects',
|
'recently_used_projects',
|
||||||
'history_default_tab',
|
'history_default_tab',
|
||||||
'default_issue_query',
|
'default_issue_query',
|
||||||
|
'default_project_query',
|
||||||
'toolbar_language_options')
|
'toolbar_language_options')
|
||||||
|
|
||||||
TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
|
TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
|
||||||
@@ -120,6 +121,9 @@ class UserPreference < ActiveRecord::Base
|
|||||||
def default_issue_query; self[:default_issue_query] end
|
def default_issue_query; self[:default_issue_query] end
|
||||||
def default_issue_query=(value); self[:default_issue_query]=value; end
|
def default_issue_query=(value); self[:default_issue_query]=value; end
|
||||||
|
|
||||||
|
def default_project_query; self[:default_project_query] end
|
||||||
|
def default_project_query=(value); self[:default_project_query]=value; end
|
||||||
|
|
||||||
# Returns the names of groups that are displayed on user's page
|
# Returns the names of groups that are displayed on user's page
|
||||||
# Example:
|
# Example:
|
||||||
# preferences.my_page_groups
|
# preferences.my_page_groups
|
||||||
|
|||||||
@@ -28,6 +28,11 @@
|
|||||||
</p>
|
</p>
|
||||||
<%= render_query_columns_selection(query,
|
<%= render_query_columns_selection(query,
|
||||||
:name => 'settings[project_list_defaults][column_names]') %>
|
:name => 'settings[project_list_defaults][column_names]') %>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label><%= l(:label_default_query) %></label>
|
||||||
|
<%= setting_select :default_project_query, default_global_project_query_options, label: false %>
|
||||||
|
</p>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,5 @@
|
|||||||
<p><%= pref_fields.select :history_default_tab, history_default_tab_options %></p>
|
<p><%= pref_fields.select :history_default_tab, history_default_tab_options %></p>
|
||||||
<p><%= pref_fields.text_area :toolbar_language_options, :rows => 4 %></p>
|
<p><%= pref_fields.text_area :toolbar_language_options, :rows => 4 %></p>
|
||||||
<p><%= pref_fields.select :default_issue_query, default_issue_query_options(@user), include_blank: l(:label_none) %></p>
|
<p><%= pref_fields.select :default_issue_query, default_issue_query_options(@user), include_blank: l(:label_none) %></p>
|
||||||
|
<p><%= pref_fields.select :default_project_query, default_project_query_options(@user), include_blank: l(:label_none) %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -410,6 +410,7 @@ en:
|
|||||||
field_toolbar_language_options: Code highlighting toolbar languages
|
field_toolbar_language_options: Code highlighting toolbar languages
|
||||||
field_twofa_required: Require two factor authentication
|
field_twofa_required: Require two factor authentication
|
||||||
field_default_issue_query: Default issue query
|
field_default_issue_query: Default issue query
|
||||||
|
field_default_project_query: Default project query
|
||||||
|
|
||||||
setting_app_title: Application title
|
setting_app_title: Application title
|
||||||
setting_welcome_text: Welcome text
|
setting_welcome_text: Welcome text
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ project_list_defaults:
|
|||||||
- name
|
- name
|
||||||
- identifier
|
- identifier
|
||||||
- short_description
|
- short_description
|
||||||
|
default_project_query:
|
||||||
|
default: ''
|
||||||
issue_done_ratio:
|
issue_done_ratio:
|
||||||
default: 'issue_field'
|
default: 'issue_field'
|
||||||
default_projects_public:
|
default_projects_public:
|
||||||
|
|||||||
33
test/fixtures/queries.yml
vendored
33
test/fixtures/queries.yml
vendored
@@ -182,4 +182,37 @@ queries_010:
|
|||||||
---
|
---
|
||||||
- - spent_on
|
- - spent_on
|
||||||
- desc
|
- desc
|
||||||
|
queries_011:
|
||||||
|
id: 11
|
||||||
|
type: ProjectQuery
|
||||||
|
visibility: 2
|
||||||
|
name: Projects as list
|
||||||
|
filters: |
|
||||||
|
---
|
||||||
|
id:
|
||||||
|
:values:
|
||||||
|
- "mine"
|
||||||
|
:operator: =
|
||||||
|
|
||||||
|
column_names:
|
||||||
|
group_by:
|
||||||
|
sort_criteria:
|
||||||
|
options: |
|
||||||
|
---
|
||||||
|
:display_type: list
|
||||||
|
queries_012:
|
||||||
|
id: 12
|
||||||
|
type: ProjectQuery
|
||||||
|
visibility: 1
|
||||||
|
name: My bookmarks
|
||||||
|
filters: |
|
||||||
|
---
|
||||||
|
id:
|
||||||
|
:values:
|
||||||
|
- "bookmarks"
|
||||||
|
:operator: =
|
||||||
|
|
||||||
|
user_id: 1
|
||||||
|
options: |
|
||||||
|
---
|
||||||
|
:display_type: board
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ class ProjectsControllerTest < Redmine::ControllerTest
|
|||||||
:trackers, :projects_trackers, :issue_statuses,
|
:trackers, :projects_trackers, :issue_statuses,
|
||||||
:enabled_modules, :enumerations, :boards, :messages,
|
:enabled_modules, :enumerations, :boards, :messages,
|
||||||
:attachments, :custom_fields, :custom_values, :time_entries,
|
:attachments, :custom_fields, :custom_values, :time_entries,
|
||||||
:wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
|
:wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
|
||||||
|
:roles, :queries
|
||||||
|
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
|
|
||||||
@@ -248,6 +249,28 @@ class ProjectsControllerTest < Redmine::ControllerTest
|
|||||||
assert_select ".total-for-cf-#{field.id} span.value", :text => '9'
|
assert_select ".total-for-cf-#{field.id} span.value", :text => '9'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_index_should_retrieve_default_query
|
||||||
|
query = ProjectQuery.find(11)
|
||||||
|
ProjectQuery.stubs(:default).returns query
|
||||||
|
|
||||||
|
[nil, 1].each do |user_id|
|
||||||
|
@request.session[:user_id] = user_id
|
||||||
|
get :index
|
||||||
|
assert_select 'h2', text: query.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_index_should_ignore_default_query_with_without_default
|
||||||
|
query = ProjectQuery.find(11)
|
||||||
|
ProjectQuery.stubs(:default).returns query
|
||||||
|
|
||||||
|
[nil, 1].each do |user_id|
|
||||||
|
@request.session[:user_id] = user_id
|
||||||
|
get :index, params: { set_filter: '1', without_default: '1' }
|
||||||
|
assert_select 'h2', text: I18n.t(:label_project_plural)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_autocomplete_js
|
def test_autocomplete_js
|
||||||
get(
|
get(
|
||||||
:autocomplete,
|
:autocomplete,
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ require File.expand_path('../../../test_helper', __FILE__)
|
|||||||
class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base
|
class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base
|
||||||
fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
|
fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
|
||||||
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
|
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
|
||||||
:attachments, :custom_fields, :custom_values, :custom_fields_projects, :time_entries, :issue_categories
|
:attachments, :custom_fields, :custom_values, :custom_fields_projects, :time_entries, :issue_categories,
|
||||||
|
:queries
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
super
|
super
|
||||||
@@ -212,6 +213,18 @@ class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base
|
|||||||
assert_equal version.name, json['project']['default_version']['name']
|
assert_equal version.name, json['project']['default_version']['name']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_get_project_should_not_load_default_query
|
||||||
|
query = ProjectQuery.find(11)
|
||||||
|
ProjectQuery.stubs(:default).returns query
|
||||||
|
|
||||||
|
get '/projects.json'
|
||||||
|
|
||||||
|
assert results = JSON.parse(@response.body)['projects']
|
||||||
|
|
||||||
|
assert_equal 4, results.count
|
||||||
|
assert results.detect{ |i| i['name'] == "eCookbook"}
|
||||||
|
end
|
||||||
|
|
||||||
test "POST /projects.xml with valid parameters should create the project" do
|
test "POST /projects.xml with valid parameters should create the project" do
|
||||||
with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
|
with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
|
||||||
assert_difference('Project.count') do
|
assert_difference('Project.count') do
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ class ProjectQueryTest < ActiveSupport::TestCase
|
|||||||
:issue_categories, :enumerations,
|
:issue_categories, :enumerations,
|
||||||
:groups_users,
|
:groups_users,
|
||||||
:enabled_modules,
|
:enabled_modules,
|
||||||
:custom_fields, :custom_values
|
:custom_fields, :custom_values,
|
||||||
|
:queries
|
||||||
|
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
|
|
||||||
@@ -69,4 +70,38 @@ class ProjectQueryTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_determine_default_project_query
|
||||||
|
user = User.find(1)
|
||||||
|
query = ProjectQuery.find(11)
|
||||||
|
user_query = ProjectQuery.find(12)
|
||||||
|
|
||||||
|
[nil, user, User.anonymous].each do |u|
|
||||||
|
assert_nil IssueQuery.default(user: u)
|
||||||
|
end
|
||||||
|
|
||||||
|
# only global default is set
|
||||||
|
with_settings :default_project_query => query.id do
|
||||||
|
[nil, user, User.anonymous].each do |u|
|
||||||
|
assert_equal query, ProjectQuery.default(user: u)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# user default, overrides global default
|
||||||
|
user.pref.default_project_query = user_query.id
|
||||||
|
user.pref.save
|
||||||
|
|
||||||
|
with_settings :default_project_query => query.id do
|
||||||
|
assert_equal user_query, ProjectQuery.default(user: user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_project_query_default_should_return_nil_if_default_query_destroyed
|
||||||
|
query = ProjectQuery.find(11)
|
||||||
|
|
||||||
|
Setting.default_project_query = query.id
|
||||||
|
query.destroy
|
||||||
|
|
||||||
|
assert_nil ProjectQuery.default
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user