##// END OF EJS Templates
Speeds up rendering of the project list for users who belong to hundreds of projects....
Speeds up rendering of the project list for users who belong to hundreds of projects. git-svn-id: http://svn.redmine.org/redmine/trunk@16123 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r15719:2bcbb305464d
r15741:f8df935dcada
Show More
queries_helper.rb
355 lines | 12.4 KiB | text/x-ruby | RubyLexer
/ app / helpers / queries_helper.rb
Jean-Philippe Lang
Added encoding comment to helpers (#9792)....
r8090 # encoding: utf-8
#
Jean-Philippe Lang
Shortens filter param names....
r5159 # Redmine - project management software
Jean-Philippe Lang
Updates copyright for 2016....
r14856 # Copyright (C) 2006-2016 Jean-Philippe Lang
Jean-Philippe Lang
Added the ability to customize columns of a saved query....
r771 #
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
Toshi MARUYAMA
remove trailing white-spaces from app/helpers/queries_helper.rb....
r6767 #
Jean-Philippe Lang
Added the ability to customize columns of a saved query....
r771 # This program 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 General Public License for more details.
Toshi MARUYAMA
remove trailing white-spaces from app/helpers/queries_helper.rb....
r6767 #
Jean-Philippe Lang
Added the ability to customize columns of a saved query....
r771 # You should have received a copy of the GNU 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.
Jean-Philippe Lang
"queries" branch merged...
r92
Jean-Philippe Lang
Added the ability to customize columns of a saved query....
r771 module QueriesHelper
Jean-Philippe Lang
Fixed that Link custom fields are not displayed as links on the issue list (#16496)....
r12779 include ApplicationHelper
Jean-Philippe Lang
Build issue filters using javascript....
r9979 def filters_options_for_select(query)
Jean-Philippe Lang
Group filters in the filter select list (#13849)....
r13280 ungrouped = []
grouped = {}
query.available_filters.map do |field, field_options|
Jean-Philippe Lang
Remove special behaviour for listing issue time entries, use a filter for that....
r15262 if field_options[:type] == :relation
Jean-Philippe Lang
Change "Related issues" label for generic grouped query filters (#22147)....
r14972 group = :label_relations
Jean-Philippe Lang
Remove special behaviour for listing issue time entries, use a filter for that....
r15262 elsif field_options[:type] == :tree
group = query.is_a?(IssueQuery) ? :label_relations : nil
Jean-Philippe Lang
Group filters in the filter select list (#13849)....
r13280 elsif field =~ /^(.+)\./
# association filters
group = "field_#{$1}"
elsif %w(member_of_group assigned_to_role).include?(field)
group = :field_assigned_to
elsif field_options[:type] == :date_past || field_options[:type] == :date
group = :label_date
end
if group
(grouped[group] ||= []) << [field_options[:name], field]
else
ungrouped << [field_options[:name], field]
end
end
# Don't group dates if there's only one (eg. time entries filters)
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 if grouped[:label_date].try(:size) == 1
Jean-Philippe Lang
Group filters in the filter select list (#13849)....
r13280 ungrouped << grouped.delete(:label_date).first
end
s = options_for_select([[]] + ungrouped)
if grouped.present?
localized_grouped = grouped.map {|k,v| [l(k), v]}
s << grouped_options_for_select(localized_grouped)
Jean-Philippe Lang
Build issue filters using javascript....
r9979 end
Jean-Philippe Lang
Group filters in the filter select list (#13849)....
r13280 s
Jean-Philippe Lang
"queries" branch merged...
r92 end
Toshi MARUYAMA
remove trailing white-spaces from app/helpers/queries_helper.rb....
r6767
Jean-Philippe Lang
Fixed that CSV Export of Spent Time ignores filters and columns selection (#13618)....
r11466 def query_filters_hidden_tags(query)
tags = ''.html_safe
query.filters.each do |field, options|
tags << hidden_field_tag("f[]", field, :id => nil)
tags << hidden_field_tag("op[#{field}]", options[:operator], :id => nil)
options[:values].each do |value|
tags << hidden_field_tag("v[#{field}][]", value, :id => nil)
end
end
tags
end
def query_columns_hidden_tags(query)
tags = ''.html_safe
query.columns.each do |column|
tags << hidden_field_tag("c[]", column.name, :id => nil)
end
tags
end
def query_hidden_tags(query)
query_filters_hidden_tags(query) + query_columns_hidden_tags(query)
end
Jean-Philippe Lang
Make time entries groupable (#16843)....
r15267 def group_by_column_select_tag(query)
options = [[]] + query.groupable_columns.collect {|c| [c.caption, c.name.to_s]}
select_tag('group_by', options_for_select(options, @query.group_by))
end
Jean-Philippe Lang
Adds an option for displaying the issue description on the issue list (#3447)....
r10721 def available_block_columns_tags(query)
tags = ''.html_safe
query.available_block_columns.each do |column|
Jean-Philippe Lang
Removes duplicate ids (#15485)....
r12378 tags << content_tag('label', check_box_tag('c[]', column.name.to_s, query.has_column?(column), :id => nil) + " #{column.caption}", :class => 'inline')
Jean-Philippe Lang
Adds an option for displaying the issue description on the issue list (#3447)....
r10721 end
tags
end
Jean-Philippe Lang
Adds options to display totals on the issue list (#1561)....
r14260 def available_totalable_columns_tags(query)
tags = ''.html_safe
query.available_totalable_columns.each do |column|
tags << content_tag('label', check_box_tag('t[]', column.name.to_s, query.totalable_columns.include?(column), :id => nil) + " #{column.caption}", :class => 'inline')
end
Jean-Philippe Lang
Totals cannot be removed completely if some columns are set in the global settings (#22123)....
r15128 tags << hidden_field_tag('t[]', '')
Jean-Philippe Lang
Adds options to display totals on the issue list (#1561)....
r14260 tags
end
Jean-Philippe Lang
Adds helpers for query columns selection....
r11221 def query_available_inline_columns_options(query)
(query.available_inline_columns - query.columns).reject(&:frozen?).collect {|column| [column.caption, column.name]}
end
def query_selected_inline_columns_options(query)
(query.inline_columns & query.available_inline_columns).reject(&:frozen?).collect {|column| [column.caption, column.name]}
end
Jean-Philippe Lang
Adds an helper for rendering query columns selection....
r11222 def render_query_columns_selection(query, options={})
tag_name = (options[:name] || 'c') + '[]'
render :partial => 'queries/columns', :locals => {:query => query, :tag_name => tag_name}
end
Jean-Philippe Lang
Make time entries groupable (#16843)....
r15267 def grouped_query_results(items, query, item_count_by_group, &block)
previous_group, first = false, true
totals_by_group = query.totalable_columns.inject({}) do |h, column|
h[column] = query.total_by_group_for(column)
h
end
items.each do |item|
group_name = group_count = nil
if query.grouped?
group = query.group_by_column.value(item)
if first || group != previous_group
if group.blank? && group != false
group_name = "(#{l(:label_blank_value)})"
else
group_name = format_object(group)
end
group_name ||= ""
group_count = item_count_by_group ? item_count_by_group[group] : nil
group_totals = totals_by_group.map {|column, t| total_tag(column, t[group] || 0)}.join(" ").html_safe
end
end
yield item, group_name, group_count, group_totals
previous_group, first = group, false
end
end
Jean-Philippe Lang
Adds options to display totals on the issue list (#1561)....
r14260 def render_query_totals(query)
return unless query.totalable_columns.present?
totals = query.totalable_columns.map do |column|
Jean-Philippe Lang
Display totals for each group on grouped queries (#1561)....
r14283 total_tag(column, query.total_for(column))
Jean-Philippe Lang
Adds options to display totals on the issue list (#1561)....
r14260 end
content_tag('p', totals.join(" ").html_safe, :class => "query-totals")
end
Jean-Philippe Lang
Display totals for each group on grouped queries (#1561)....
r14283 def total_tag(column, value)
label = content_tag('span', "#{column.caption}:")
Jean-Philippe Lang
Introduce a setting to change the display format of timespans to h:mm (#23996)....
r15583 value = if [:hours, :spent_hours, :total_spent_hours, :estimated_hours].include? column.name
format_hours(value)
else
format_object(value)
end
value = content_tag('span', value, :class => 'value')
Jean-Philippe Lang
Display totals for each group on grouped queries (#1561)....
r14283 content_tag('span', label + " " + value, :class => "total-for-#{column.name.to_s.dasherize}")
end
Jean-Philippe Lang
Added the ability to customize columns of a saved query....
r771 def column_header(column)
Jean-Philippe Lang
Validates sort_key and sort_order params (#2378)....
r2169 column.sortable ? sort_header_tag(column.name.to_s, :caption => column.caption,
Toshi MARUYAMA
remove trailing white-spaces from app/helpers/queries_helper.rb....
r6767 :default_order => column.default_order) :
Jean-Philippe Lang
Additional escaping....
r6207 content_tag('th', h(column.caption))
Jean-Philippe Lang
Added the ability to customize columns of a saved query....
r771 end
Toshi MARUYAMA
remove trailing white-spaces from app/helpers/queries_helper.rb....
r6767
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 def column_content(column, item)
value = column.value_object(item)
Jean-Philippe Lang
Adds support for multiselect custom fields (#1189)....
r8601 if value.is_a?(Array)
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 value.collect {|v| column_value(column, item, v)}.compact.join(', ').html_safe
Jean-Philippe Lang
Adds support for multiselect custom fields (#1189)....
r8601 else
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 column_value(column, item, value)
Jean-Philippe Lang
Adds support for multiselect custom fields (#1189)....
r8601 end
end
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719
def column_value(column, item, value)
Jean-Philippe Lang
Extract generic formatting options to an helper....
r12087 case column.name
when :id
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 link_to value, issue_path(item)
Jean-Philippe Lang
Extract generic formatting options to an helper....
r12087 when :subject
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 link_to value, issue_path(item)
Jean-Philippe Lang
Fixed that parent column should not include issue subject (#13673)....
r13174 when :parent
value ? (value.visible? ? link_to_issue(value, :subject => false) : "##{value.id}") : ''
Jean-Philippe Lang
Extract generic formatting options to an helper....
r12087 when :description
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 item.description? ? content_tag('div', textilizable(item, :description), :class => "wiki") : ''
Jean-Philippe Lang
Extract generic formatting options to an helper....
r12087 when :done_ratio
Jean-Philippe Lang
Improved responsiveness for versions and roadmap (#19097)....
r14469 progress_bar(value)
Jean-Philippe Lang
Extract generic formatting options to an helper....
r12087 when :relations
Jean-Philippe Lang
Makes related issues available for display and filtering on the issue list (#3239, #3265)....
r10303 content_tag('span',
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 value.to_s(item) {|other| link_to_issue(other, :subject => false, :tracker => false)}.html_safe,
:class => value.css_classes_for(item))
Jean-Philippe Lang
Introduce a setting to change the display format of timespans to h:mm (#23996)....
r15583 when :hours, :spent_hours, :total_spent_hours, :estimated_hours
format_hours(value)
Jean-Philippe Lang
Fixed: "None" category issue count is empty while grouping by category (#4308)....
r2998 else
Jean-Philippe Lang
Extract generic formatting options to an helper....
r12087 format_object(value)
Jean-Philippe Lang
Added the ability to customize columns of a saved query....
r771 end
end
Eric Davis
Refactor: move method to helper....
r3577
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 def csv_content(column, item)
value = column.value_object(item)
Jean-Philippe Lang
Fixed that float custom fields do not use CSV decimal separator (#10364)....
r11211 if value.is_a?(Array)
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 value.collect {|v| csv_value(column, item, v)}.compact.join(', ')
Jean-Philippe Lang
Fixed that float custom fields do not use CSV decimal separator (#10364)....
r11211 else
Jean-Philippe Lang
Rename "issue" to "item" in query helpers (#24643)....
r15719 csv_value(column, item, value)
Jean-Philippe Lang
Fixed that float custom fields do not use CSV decimal separator (#10364)....
r11211 end
end
Jean-Philippe Lang
Time entries CSV export should include the tracker and subject of the issue (#18269)....
r13180 def csv_value(column, object, value)
Jean-Philippe Lang
Fixed that Link custom fields are not displayed as links on the issue list (#16496)....
r12779 format_object(value, false) do |value|
case value.class.name
when 'Float'
sprintf("%.2f", value).gsub('.', l(:general_csv_decimal_separator))
when 'IssueRelation'
Jean-Philippe Lang
Use IssueRelation#to_s....
r13183 value.to_s(object)
Jean-Philippe Lang
Fixed CSV content for parent issue column (#13608)....
r13173 when 'Issue'
Jean-Philippe Lang
Time entries CSV export should include the tracker and subject of the issue (#18269)....
r13180 if object.is_a?(TimeEntry)
"#{value.tracker} ##{value.id}: #{value.subject}"
else
value.id
end
Jean-Philippe Lang
Fixed that Link custom fields are not displayed as links on the issue list (#16496)....
r12779 else
value
end
Jean-Philippe Lang
Fixed that float custom fields do not use CSV decimal separator (#10364)....
r11211 end
end
Jean-Philippe Lang
Refactor: #issues_to_csv and #entries_to_csv merged into QueriesHelper#query_to_csv....
r11218 def query_to_csv(items, query, options={})
Jean-Philippe Lang
Isolates csv options for a hash param (#1159)....
r14292 options ||= {}
Jean-Philippe Lang
Refactor: #issues_to_csv and #entries_to_csv merged into QueriesHelper#query_to_csv....
r11218 columns = (options[:columns] == 'all' ? query.available_inline_columns : query.inline_columns)
query.available_block_columns.each do |column|
if options[column.name].present?
columns << column
end
end
Jean-Philippe Lang
Adds a class for handling CSV generation (#7037)....
r13920 Redmine::Export::CSV.generate do |csv|
Jean-Philippe Lang
Refactor: #issues_to_csv and #entries_to_csv merged into QueriesHelper#query_to_csv....
r11218 # csv header fields
Jean-Philippe Lang
Adds a class for handling CSV generation (#7037)....
r13920 csv << columns.map {|c| c.caption.to_s}
Jean-Philippe Lang
Refactor: #issues_to_csv and #entries_to_csv merged into QueriesHelper#query_to_csv....
r11218 # csv lines
items.each do |item|
Jean-Philippe Lang
Adds a class for handling CSV generation (#7037)....
r13920 csv << columns.map {|c| csv_content(c, item)}
Jean-Philippe Lang
Refactor: #issues_to_csv and #entries_to_csv merged into QueriesHelper#query_to_csv....
r11218 end
end
end
Eric Davis
Refactor: move method to helper....
r3577 # Retrieve query from session or build a new query
Jean-Philippe Lang
Makes spent time queries savable (#14790)....
r15257 def retrieve_query(klass=IssueQuery, use_session=true)
session_key = klass.name.underscore.to_sym
if params[:query_id].present?
Eric Davis
Refactor: move method to helper....
r3577 cond = "project_id IS NULL"
cond << " OR project_id = #{@project.id}" if @project
Jean-Philippe Lang
Makes spent time queries savable (#14790)....
r15257 @query = klass.where(cond).find(params[:query_id])
Jean-Philippe Lang
Fixed: private queries should not be accessible to other users (#8729)....
r6043 raise ::Unauthorized unless @query.visible?
Etienne Massip
Reverted removal of project assignment to query (#9108)....
r7536 @query.project = @project
Jean-Philippe Lang
Makes spent time queries savable (#14790)....
r15257 session[session_key] = {:id => @query.id, :project_id => @query.project_id} if use_session
Eric Davis
Refactor: move method to helper....
r3577 sort_clear
Jean-Philippe Lang
Makes spent time queries savable (#14790)....
r15257 elsif api_request? || params[:set_filter] || !use_session || session[session_key].nil? || session[session_key][:project_id] != (@project ? @project.id : nil)
Etienne Massip
Refactor : convert queries to REST resources (also fixes #9108)....
r7529 # Give it a name, required to be valid
Jean-Philippe Lang
Makes spent time queries savable (#14790)....
r15257 @query = klass.new(:name => "_", :project => @project)
Jean-Philippe Lang
Moved build_query_from_params helper to Query#build_from_params....
r10739 @query.build_from_params(params)
Jean-Philippe Lang
Makes spent time queries savable (#14790)....
r15257 session[session_key] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names, :totalable_names => @query.totalable_names} if use_session
Eric Davis
Refactor: move method to helper....
r3577 else
Etienne Massip
Refactor : convert queries to REST resources (also fixes #9108)....
r7529 # retrieve from session
Jean-Philippe Lang
Test failures with ruby1.8....
r11789 @query = nil
Jean-Philippe Lang
Makes spent time queries savable (#14790)....
r15257 @query = klass.find_by_id(session[session_key][:id]) if session[session_key][:id]
@query ||= klass.new(:name => "_", :filters => session[session_key][:filters], :group_by => session[session_key][:group_by], :column_names => session[session_key][:column_names], :totalable_names => session[session_key][:totalable_names])
Jean-Philippe Lang
Fixed that a cross-project custom query is not remembered inside project (#9738)....
r7993 @query.project = @project
Etienne Massip
Refactor : convert queries to REST resources (also fixes #9108)....
r7529 end
end
Etienne Massip
Reverted removal of project assignment to query (#9108)....
r7536
Jean-Philippe Lang
Previous/Next navigation on a issue is not displayed on r15639 and later (#23781)....
r15468 def retrieve_query_from_session(klass=IssueQuery)
session_key = klass.name.underscore.to_sym
session_data = session[session_key]
if session_data
if session_data[:id]
@query = IssueQuery.find_by_id(session_data[:id])
Jean-Philippe Lang
Fixed previous/next links when navigating in a saved query....
r8537 return unless @query
else
Jean-Philippe Lang
Previous/Next navigation on a issue is not displayed on r15639 and later (#23781)....
r15468 @query = IssueQuery.new(:name => "_", :filters => session_data[:filters], :group_by => session_data[:group_by], :column_names => session_data[:column_names], :totalable_names => session_data[:totalable_names])
Jean-Philippe Lang
Fixed previous/next links when navigating in a saved query....
r8537 end
Jean-Philippe Lang
Previous/Next navigation on a issue is not displayed on r15639 and later (#23781)....
r15468 if session_data.has_key?(:project_id)
@query.project_id = session_data[:project_id]
Jean-Philippe Lang
Adds previous/next links to issue (#2850)....
r8368 else
@query.project = @project
end
@query
end
end
Jean-Philippe Lang
Adds query params as hidden field tags to the CSV export form (#22108)....
r14820
# Returns the query definition as hidden field tags
def query_as_hidden_field_tags(query)
tags = hidden_field_tag("set_filter", "1", :id => nil)
if query.filters.present?
query.filters.each do |field, filter|
tags << hidden_field_tag("f[]", field, :id => nil)
tags << hidden_field_tag("op[#{field}]", filter[:operator], :id => nil)
filter[:values].each do |value|
tags << hidden_field_tag("v[#{field}][]", value, :id => nil)
end
end
Jean-Philippe Lang
Wrong filters are applied when exporting issues to CSV with blank filter (#23206)....
r15226 else
tags << hidden_field_tag("f[]", "", :id => nil)
Jean-Philippe Lang
Adds query params as hidden field tags to the CSV export form (#22108)....
r14820 end
if query.column_names.present?
query.column_names.each do |name|
tags << hidden_field_tag("c[]", name, :id => nil)
end
end
if query.totalable_names.present?
query.totalable_names.each do |name|
tags << hidden_field_tag("t[]", name, :id => nil)
end
end
if query.group_by.present?
tags << hidden_field_tag("group_by", query.group_by, :id => nil)
end
tags
end
Jean-Philippe Lang
Moves sidebar queries rendering to QueriesHelper (#14790)....
r15258
Jean-Philippe Lang
Display the list of saved queries in the sidebar (#14790)....
r15260 # Returns the queries that are rendered in the sidebar
def sidebar_queries(klass, project)
klass.visible.global_or_on_project(@project).sorted.to_a
Jean-Philippe Lang
Moves sidebar queries rendering to QueriesHelper (#14790)....
r15258 end
Jean-Philippe Lang
Display the list of saved queries in the sidebar (#14790)....
r15260 # Renders a group of queries
Jean-Philippe Lang
Moves sidebar queries rendering to QueriesHelper (#14790)....
r15258 def query_links(title, queries)
return '' if queries.empty?
# links to #index on issues/show
url_params = controller_name == 'issues' ? {:controller => 'issues', :action => 'index', :project_id => @project} : {}
content_tag('h3', title) + "\n" +
content_tag('ul',
queries.collect {|query|
css = 'query'
css << ' selected' if query == @query
content_tag('li', link_to(query.name, url_params.merge(:query_id => query), :class => css))
}.join("\n").html_safe,
:class => 'queries'
) + "\n"
end
Jean-Philippe Lang
Display the list of saved queries in the sidebar (#14790)....
r15260 # Renders the list of queries for the sidebar
def render_sidebar_queries(klass, project)
queries = sidebar_queries(klass, project)
Jean-Philippe Lang
Moves sidebar queries rendering to QueriesHelper (#14790)....
r15258 out = ''.html_safe
Jean-Philippe Lang
Display the list of saved queries in the sidebar (#14790)....
r15260 out << query_links(l(:label_my_queries), queries.select(&:is_private?))
out << query_links(l(:label_query_plural), queries.reject(&:is_private?))
Jean-Philippe Lang
Moves sidebar queries rendering to QueriesHelper (#14790)....
r15258 out
end
Jean-Philippe Lang
"queries" branch merged...
r92 end