add_custom_fields_filters(IssueCustomField.find(:all, :conditions => {:is_filter => true, :is_for_all => true}))
end
+ add_associations_custom_fields_filters :project, :author, :assigned_to, :fixed_version
+
if User.current.allowed_to?(:set_issues_private, nil, :global => true) ||
User.current.allowed_to?(:set_own_issues_private, nil, :global => true)
@available_filters["is_private"] = { :type => :list, :order => 15, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]] }
end
end
- if field =~ /^cf_(\d+)$/
+ if field =~ /cf_(\d+)$/
# custom field
filters_clauses << sql_for_custom_field(field, operator, v, $1)
elsif respond_to?("sql_for_#{field}_field")
db_table = CustomValue.table_name
db_field = 'value'
filter = @available_filters[field]
- if filter && filter[:format] == 'user'
+ return nil unless filter
+ if filter[:format] == 'user'
if value.delete('me')
value.push User.current.id.to_s
end
operator = '='
not_in = 'NOT'
end
- "#{Issue.table_name}.id #{not_in} IN (SELECT #{Issue.table_name}.id FROM #{Issue.table_name} LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='Issue' AND #{db_table}.customized_id=#{Issue.table_name}.id AND #{db_table}.custom_field_id=#{custom_field_id} WHERE " +
+ customized_key = "id"
+ customized_class = Issue
+ if field =~ /^(.+)\.cf_/
+ assoc = $1
+ customized_key = "#{assoc}_id"
+ customized_class = Issue.reflect_on_association(assoc.to_sym).klass.base_class rescue nil
+ raise "Unknown Issue association #{assoc}" unless customized_class
+ end
+ "#{Issue.table_name}.#{customized_key} #{not_in} IN (SELECT #{customized_class.table_name}.id FROM #{customized_class.table_name} LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='#{customized_class}' AND #{db_table}.customized_id=#{customized_class.table_name}.id AND #{db_table}.custom_field_id=#{custom_field_id} WHERE " +
sql_for_field(field, operator, value, db_table, db_field, true) + ')'
end
return sql
end
- def add_custom_fields_filters(custom_fields)
+ def add_custom_fields_filters(custom_fields, assoc=nil)
+ return unless custom_fields.present?
@available_filters ||= {}
custom_fields.select(&:is_filter?).each do |field|
else
options = { :type => :string, :order => 20 }
end
- @available_filters["cf_#{field.id}"] = options.merge({ :name => field.name, :format => field.field_format })
+ filter_id = "cf_#{field.id}"
+ filter_name = field.name
+ if assoc.present?
+ filter_id = "#{assoc}.#{filter_id}"
+ filter_name = l("label_attribute_of_#{assoc}", :name => filter_name)
+ end
+ @available_filters[filter_id] = options.merge({ :name => filter_name, :format => field.field_format })
+ end
+ end
+
+ def add_associations_custom_fields_filters(*associations)
+ fields_by_class = CustomField.where(:is_filter => true).group_by(&:class)
+ associations.each do |assoc|
+ association_klass = Issue.reflect_on_association(assoc).klass
+ fields_by_class.each do |field_class, fields|
+ if field_class.customized_class <= association_klass
+ add_custom_fields_filters(fields, assoc)
+ end
+ end
end
end
<p><%= f.check_box :is_required %></p>
<p><%= f.check_box :visible %></p>
<p><%= f.check_box :editable %></p>
+ <p><%= f.check_box :is_filter %></p>
<% when "ProjectCustomField" %>
<p><%= f.check_box :is_required %></p>
<p><%= f.check_box :visible %></p>
<p><%= f.check_box :searchable %></p>
+ <p><%= f.check_box :is_filter %></p>
+
+<% when "VersionCustomField" %>
+ <p><%= f.check_box :is_required %></p>
+ <p><%= f.check_box :is_filter %></p>
+
+<% when "GroupCustomField" %>
+ <p><%= f.check_box :is_required %></p>
+ <p><%= f.check_box :is_filter %></p>
<% when "TimeEntryCustomField" %>
<p><%= f.check_box :is_required %></p>
label_fields_permissions: Fields permissions
label_readonly: Read-only
label_required: Required
+ label_attribute_of_project: "Project's %{name}"
+ label_attribute_of_author: "Author's %{name}"
+ label_attribute_of_assigned_to: "Assignee's %{name}"
+ label_attribute_of_fixed_version: "Target version's %{name}"
button_login: Login
button_submit: Submit
label_fields_permissions: Permissions sur les champs
label_readonly: Lecture
label_required: Obligatoire
+ label_attribute_of_project: "%{name} du projet"
+ label_attribute_of_author: "%{name} de l'auteur"
+ label_attribute_of_assigned_to: "%{name} de l'assigné"
+ label_attribute_of_fixed_version: "%{name} de la version cible"
button_login: Connexion
button_submit: Soumettre
var option = $('<option>');
if ($.isArray(filterValue)) {
option.val(filterValue[1]).html(filterValue[0]);
+ if (values.indexOf(filterValue[1]) > -1) {option.attr('selected', true)};
} else {
option.val(filterValue).html(filterValue);
+ if (values.indexOf(filterValue) > -1) {option.attr('selected', true)};
}
- if (values.indexOf(filterValues[i][1]) > -1) {option.attr('selected', true)};
select.append(option);
}
break;
fieldset#filters table { border-collapse: collapse; }
fieldset#filters table td { padding: 0; vertical-align: middle; }
fieldset#filters tr.filter { height: 2.1em; }
-fieldset#filters td.field { width:200px; }
+fieldset#filters td.field { width:250px; }
fieldset#filters td.operator { width:170px; }
fieldset#filters td.values { white-space:nowrap; }
fieldset#filters td.values select {min-width:130px;}
assert_equal({}, query.filters)
end
+ def test_index_with_project_custom_field_filter
+ field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
+ CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
+ CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
+ filter_name = "project.cf_#{field.id}"
+ @request.session[:user_id] = 1
+
+ get :index, :set_filter => 1,
+ :f => [filter_name],
+ :op => {filter_name => '='},
+ :v => {filter_name => ['Foo']}
+ assert_response :success
+ assert_template 'index'
+ assert_equal [3, 5], assigns(:issues).map(&:project_id).uniq.sort
+ end
+
def test_index_with_query
get :index, :project_id => 1, :query_id => 5
assert_response :success
User.current = nil
end
+ def test_filter_on_project_custom_field
+ field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
+ CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
+ CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
+
+ query = Query.new(:name => '_')
+ filter_name = "project.cf_#{field.id}"
+ assert_include filter_name, query.available_filters.keys
+ query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
+ assert_equal [3, 5], find_issues_with_query(query).map(&:project_id).uniq.sort
+ end
+
+ def test_filter_on_author_custom_field
+ field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
+ CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
+
+ query = Query.new(:name => '_')
+ filter_name = "author.cf_#{field.id}"
+ assert_include filter_name, query.available_filters.keys
+ query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
+ assert_equal [3], find_issues_with_query(query).map(&:author_id).uniq.sort
+ end
+
+ def test_filter_on_assigned_to_custom_field
+ field = UserCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
+ CustomValue.create!(:custom_field => field, :customized => User.find(3), :value => 'Foo')
+
+ query = Query.new(:name => '_')
+ filter_name = "assigned_to.cf_#{field.id}"
+ assert_include filter_name, query.available_filters.keys
+ query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
+ assert_equal [3], find_issues_with_query(query).map(&:assigned_to_id).uniq.sort
+ end
+
+ def test_filter_on_fixed_version_custom_field
+ field = VersionCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
+ CustomValue.create!(:custom_field => field, :customized => Version.find(2), :value => 'Foo')
+
+ query = Query.new(:name => '_')
+ filter_name = "fixed_version.cf_#{field.id}"
+ assert_include filter_name, query.available_filters.keys
+ query.filters = {filter_name => {:operator => '=', :values => ['Foo']}}
+ assert_equal [2], find_issues_with_query(query).map(&:fixed_version_id).uniq.sort
+ end
+
def test_statement_should_be_nil_with_no_filters
q = Query.new(:name => '_')
q.filters = {}