module SmartTable
module SmartTableHelper
# Renders pagination controls (centered, usually below the table). Usage:
#
# <%= smart_table_paginate @records, @total_records_count, Record.model_name.human %>
#
# This method requires the loaded records for the current page and the total
# record count (sum of all pages). It also requires the listed record's human
# name, so it can generate a human sentence for the number of records shown.
#
# When the user clicks on one of the page size's links, a new request to the
# index action is made, including a page number parameter available through
# smart_table_params.limit and smart_table_params.offset.
#
# These values can be passed to ActiveRecord directly, e.g.:
#
# @records = Record.
# limit(smart_table_params.limit).
# offset(smart_table_params.offset)
def smart_table_paginate(records, total_records_count, record_model_name)
raise 'smart_table_params must be called on the controller, before using smart_table_paginate helper' unless get_cached_smart_table_params
paginatable_array = Kaminari.
paginate_array(records, total_count: total_records_count).
page(get_cached_smart_table_params.page_number).
per(get_cached_smart_table_params.page_size)
html_elements = []
# call to Kaminari view helper
html_elements << paginate(paginatable_array, param_name: PAGE_PARAM, theme: "smart_table")
html_elements << content_tag(:div, class: 'text-center') do
# call to Kaminari view helper
page_entries_info(paginatable_array, entry_name: record_model_name.downcase)
end
html_elements.join.html_safe
end
SORT_ORDERS = ["asc", "desc"]
# Renders table header with sortable feature. Usage:
#
#
<%= smart_table_sortable("Header Text", :attribute_name) %> |
#
# This will generate a link that will make a new request to your index page,
# including a sort parameter that will be available through smart_table_params.sort.
# You can simply pass this parameter to ActiveRecord:
#
# @records = Record.order(smart_table_params.sort)
def smart_table_sortable(text, attribute)
raise 'smart_table_params must be called on the controller, before using smart_table_sortable helper' unless get_cached_smart_table_params
current_sort_state = get_cached_smart_table_params.sort
attribute = attribute.to_s
current_sort_attribute, current_sort_order = if current_sort_state.present?
current_sort_state.downcase.split
else
nil
end
next_sort_order = if current_sort_attribute == attribute
SORT_ORDERS[(SORT_ORDERS.index(current_sort_order) + 1) % SORT_ORDERS.size]
else
SORT_ORDERS.first
end
link_url = current_request_url_with_merged_query_params(SORT_PARAM => "#{attribute} #{next_sort_order}")
link_to link_url do
text.html_safe + ' ' + (
if current_sort_attribute == attribute && current_sort_order == 'asc'
"".html_safe
elsif current_sort_attribute == attribute && current_sort_order == 'desc'
"".html_safe
else
"".html_safe
end
)
end
end
# Renders table page size selector (centered, usually below the table). Usage:
#
# <%= smart_table_page_size_selector @total_records_count, Record.model_name.human %>
#
# This method requires the total number of records, so it can prune the list
# of available page size to only the ones that make sense for a certain
# number of records. It also requires the listed record's human name, so
# it can generate a human sentence for the number of records shown.
#
# When the user clicks on one of the page size's links, a new request to the
# index action is made, including a page size parameter available through
# smart_table_params.limit and smart_table_params.offset.
#
# These values can be passed to ActiveRecord directly, e.g.:
#
# @records = Record.
# limit(smart_table_params.limit).
# offset(smart_table_params.offset)
def smart_table_page_size_selector(total_records_count, record_model_name)
raise 'smart_table_params must be called on the controller, before using smart_table_page_size_selector helper' unless get_cached_smart_table_params
page_sizes = PAGE_SIZES.dup
page_sizes << get_cached_smart_table_params.page_size.to_i if get_cached_smart_table_params.page_size
page_sizes.sort!
if page_sizes.last >= total_records_count || get_cached_smart_table_params.page_size.nil?
page_sizes.reject! {|size| size > total_records_count}
page_sizes << SHOW_ALL
end
content_tag(:div, class: 'text-center') do
(
record_model_name.pluralize + ' ' +
I18n.t('smart_table.per_page') + ': ' +
page_sizes.map do |page_size|
if page_size == get_cached_smart_table_params.page_size
page_size.to_s
else
human_page_size = (page_size == SHOW_ALL ? I18n.t('smart_table.show_all') : page_size.to_s)
link_to human_page_size, current_request_url_with_merged_query_params(PAGE_SIZE_PARAM => page_size)
end
end.join(' ')
).html_safe
end
end
# Renders search field (right-aligned, usually above the table). Usage:
#
#
# <%= smart_table_search %>
#
#
#
#
# ...
#
# When the user types something on the search field and focuses out (or
# presses ENTER), a new request is made to the index action, including a
# search parameter available through smart_table_params.search.
#
# You are responsible for using the search parameter to build a query in your
# own way e.g.:
#
# @records = Record.
# where(
# 'column1 LIKE ? OR column2 LIKE ?',
# *Array.new(2, "%#{ActiveRecord::Base.sanitize_sql_like(smart_table_params.search)}%")
# )
def smart_table_search
raise 'smart_table_params must be called on the controller, before using smart_table_search helper' unless get_cached_smart_table_params
text_field_tag(
SEARCH_PARAM,
get_cached_smart_table_params.search,
type: 'search', placeholder: I18n.t('smart_table.search'), class: 'smart_table_search', id: 'smart_table_search'
)
end
# Creates section for extra table filters. Usage:
#
# <%= smart_table_extra_filters do %>
# <%= check_box_tag 'somekey', 'value', params['somekey'] %>
# <%= select_tag "credit_card", options_for_select({"VISA" => 'visa', "MasterCard" => 'master_card'}, params['credit_card']) %>
# <%= text_field_tag "somefield", params['somefield'] %>
# <%= radio_button_tag("category", "", !params["category"].present?) %>
# <%= radio_button_tag("category", "rails", params["category"] == 'rails') %>
# <%= radio_button_tag("category", "java", params["category"] == 'java') %>
# <% end %>
#
# Everytime the user changes any of the fields inside this section, the page
# will be refreshed and the field value will be included to the request params.
#
# You are responsible for using the parameters by yourself when loading the
# records.
def smart_table_extra_filters(&block)
raise 'smart_table_params must be called on the controller, before using smart_table_extra_filters helper' unless get_cached_smart_table_params
content = capture(&block)
content_tag(:div,
content,
id: 'smart_table_extra_filters',
class: 'smart_table_extra_filters'
)
end
private
# generates url merging parameters to the current url
def current_request_url_with_merged_query_params(params)
request_url = URI::parse(request.url)
link_query_params = URI::decode_www_form(request_url.query || '').to_h.merge(params.stringify_keys)
link_url = request_url.dup
link_url.query = URI::encode_www_form(link_query_params)
link_url.to_s
end
end
end