You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sort_helper.rb 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # frozen_string_literal: true
  2. # Helpers to sort tables using clickable column headers.
  3. #
  4. # Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
  5. # Jean-Philippe Lang, 2009
  6. # License: This source code is released under the MIT license.
  7. #
  8. # - Consecutive clicks toggle the column's sort order.
  9. # - Sort state is maintained by a session hash entry.
  10. # - CSS classes identify sort column and state.
  11. # - Typically used in conjunction with the Pagination module.
  12. #
  13. # Example code snippets:
  14. #
  15. # Controller:
  16. #
  17. # helper :sort
  18. # include SortHelper
  19. #
  20. # def list
  21. # sort_init 'last_name'
  22. # sort_update %w(first_name last_name)
  23. # @items = Contact.find_all nil, sort_clause
  24. # end
  25. #
  26. # Controller (using Pagination module):
  27. #
  28. # helper :sort
  29. # include SortHelper
  30. #
  31. # def list
  32. # sort_init 'last_name'
  33. # sort_update %w(first_name last_name)
  34. # @contact_pages, @items = paginate :contacts,
  35. # :order_by => sort_clause,
  36. # :per_page => 10
  37. # end
  38. #
  39. # View (table header in list.rhtml):
  40. #
  41. # <thead>
  42. # <tr>
  43. # <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
  44. # <%= sort_header_tag('last_name', :caption => 'Name') %>
  45. # <%= sort_header_tag('phone') %>
  46. # <%= sort_header_tag('address', :width => 200) %>
  47. # </tr>
  48. # </thead>
  49. #
  50. # - Introduces instance variables: @sort_default, @sort_criteria
  51. # - Introduces param :sort
  52. #
  53. module SortHelper
  54. def sort_name
  55. controller_name + '_' + action_name + '_sort'
  56. end
  57. # Initializes the default sort.
  58. # Examples:
  59. #
  60. # sort_init 'name'
  61. # sort_init 'id', 'desc'
  62. # sort_init ['name', ['id', 'desc']]
  63. # sort_init [['name', 'desc'], ['id', 'desc']]
  64. #
  65. def sort_init(*args)
  66. case args.size
  67. when 1
  68. @sort_default = args.first.is_a?(Array) ? args.first : [[args.first]]
  69. when 2
  70. @sort_default = [[args.first, args.last]]
  71. else
  72. raise ArgumentError
  73. end
  74. end
  75. # Updates the sort state. Call this in the controller prior to calling
  76. # sort_clause.
  77. # - criteria can be either an array or a hash of allowed keys
  78. #
  79. def sort_update(criteria, sort_name=nil)
  80. sort_name ||= self.sort_name
  81. @sort_criteria = Redmine::SortCriteria.new(params[:sort] || session[sort_name] || @sort_default)
  82. @sortable_columns = criteria
  83. session[sort_name] = @sort_criteria.to_param
  84. end
  85. # Clears the sort criteria session data
  86. #
  87. def sort_clear
  88. session[sort_name] = nil
  89. end
  90. # Returns an SQL sort clause corresponding to the current sort state.
  91. # Use this to sort the controller's table items collection.
  92. #
  93. def sort_clause
  94. @sort_criteria.sort_clause(@sortable_columns)
  95. end
  96. def sort_criteria
  97. @sort_criteria
  98. end
  99. # Returns a link which sorts by the named column.
  100. #
  101. # - column is the name of an attribute in the sorted record collection.
  102. # - the optional caption explicitly specifies the displayed link text.
  103. # - 2 CSS classes reflect the state of the link: sort and asc or desc
  104. #
  105. def sort_link(column, caption, default_order)
  106. css, order = nil, default_order
  107. if column.to_s == @sort_criteria.first_key
  108. if @sort_criteria.first_asc?
  109. css = 'sort asc icon icon-sorted-desc'
  110. order = 'desc'
  111. else
  112. css = 'sort desc icon icon-sorted-asc'
  113. order = 'asc'
  114. end
  115. end
  116. caption = column.to_s.humanize unless caption
  117. sort_options = {:sort => @sort_criteria.add(column.to_s, order).to_param}
  118. link_to(caption, {:params => request.query_parameters.merge(sort_options)}, :class => css)
  119. end
  120. # Returns a table header <th> tag with a sort link for the named column
  121. # attribute.
  122. #
  123. # Options:
  124. # :caption The displayed link name (defaults to titleized column name).
  125. # :title The tag's 'title' attribute (defaults to 'Sort by :caption').
  126. #
  127. # Other options hash entries generate additional table header tag attributes.
  128. #
  129. # Example:
  130. #
  131. # <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
  132. #
  133. def sort_header_tag(column, options = {})
  134. caption = options.delete(:caption) || column.to_s.humanize
  135. default_order = options.delete(:default_order) || 'asc'
  136. options[:title] = l(:label_sort_by, "\"#{caption}\"") unless options[:title]
  137. content_tag('th', sort_link(column, caption, default_order), options)
  138. end
  139. # Returns the css classes for the current sort order
  140. #
  141. # Example:
  142. #
  143. # sort_css_classes
  144. # # => "sort-by-created-on sort-desc"
  145. def sort_css_classes
  146. if @sort_criteria.first_key
  147. "sort-by-#{@sort_criteria.first_key.to_s.dasherize} sort-#{@sort_criteria.first_asc? ? 'asc' : 'desc'}"
  148. end
  149. end
  150. end