acts_as_data_table 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +55 -0
- data/Rakefile +11 -0
- data/acts_as_data_table.gemspec +25 -0
- data/app/coffeescripts/acts_as_data_table.coffee +47 -0
- data/app/helpers/acts_as_data_table_helper.rb +170 -0
- data/config/locales/acts_as_data_table.en.yml +11 -0
- data/generators/acts_as_data_table/acts_as_data_table_generator.rb +13 -0
- data/generators/acts_as_data_table/templates/assets/js/acts_as_data_table.js +37 -0
- data/init.rb +1 -0
- data/lib/acts_as_data_table/multi_column_scopes.rb +116 -0
- data/lib/acts_as_data_table/scope_filters/action_controller.rb +139 -0
- data/lib/acts_as_data_table/scope_filters/active_record.rb +264 -0
- data/lib/acts_as_data_table/scope_filters/form_helper.rb +67 -0
- data/lib/acts_as_data_table/scope_filters/validator.rb +144 -0
- data/lib/acts_as_data_table/session_helper.rb +193 -0
- data/lib/acts_as_data_table/shared/action_controller.rb +25 -0
- data/lib/acts_as_data_table/shared/session.rb +312 -0
- data/lib/acts_as_data_table/sortable_columns/action_controller.rb +111 -0
- data/lib/acts_as_data_table/sortable_columns/active_record.rb +34 -0
- data/lib/acts_as_data_table/sortable_columns/renderers/bootstrap2.rb +17 -0
- data/lib/acts_as_data_table/sortable_columns/renderers/default.rb +82 -0
- data/lib/acts_as_data_table/version.rb +3 -0
- data/lib/acts_as_data_table.rb +71 -0
- data/lib/acts_as_data_table_helper.rb.bak +165 -0
- data/lib/named_scope_filters.rb +273 -0
- data/lib/tasks/acts_as_data_table.rake +4 -0
- data/rails/init.rb +4 -0
- data/test/acts_as_searchable_test.rb +8 -0
- data/test/test_helper.rb +4 -0
- metadata +142 -0
@@ -0,0 +1,312 @@
|
|
1
|
+
module Acts
|
2
|
+
module DataTable
|
3
|
+
module Shared
|
4
|
+
class Session
|
5
|
+
|
6
|
+
def initialize(session, controller_path, action_name)
|
7
|
+
@session = session
|
8
|
+
@controller_path = controller_path
|
9
|
+
@action_name = action_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def sf_session
|
13
|
+
@session[:scope_filters] ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def sc_session
|
17
|
+
@session[:sortable_columns] ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def model
|
21
|
+
Acts::DataTable::ScopeFilters::ActionController.get_request_model
|
22
|
+
end
|
23
|
+
|
24
|
+
def errors
|
25
|
+
@errors ||= {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def errors_on(context)
|
29
|
+
errors[context.to_s] || []
|
30
|
+
end
|
31
|
+
|
32
|
+
#----------------------------------------------------------------
|
33
|
+
# Filter Management
|
34
|
+
#----------------------------------------------------------------
|
35
|
+
|
36
|
+
#
|
37
|
+
# @return [Hash] all active filters for the current controller action
|
38
|
+
# by the group they are registered in.
|
39
|
+
#
|
40
|
+
def active_filters
|
41
|
+
sf_session[current_action_key] || {}
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Checks whether the given filter is currently active
|
46
|
+
# Note that it also checks if it is active with exactly the given arguments.
|
47
|
+
#
|
48
|
+
# @return [TrueClass, FalseClass] +true+ if the filter is active AND
|
49
|
+
# the given +args+ match the ones used in the filter.
|
50
|
+
#
|
51
|
+
def active_filter?(group, scope, args)
|
52
|
+
args ||= {}
|
53
|
+
used_args = Acts::DataTable.lookup_nested_hash(active_filters, group.to_s, scope.to_s)
|
54
|
+
used_args && (args.stringify_keys.to_a - used_args.to_a).empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# @return [String, NilClass] The name of the scope filter which is
|
59
|
+
# currently active in the given group or +nil+ if no filter from this group is
|
60
|
+
# currently active
|
61
|
+
#
|
62
|
+
def active_filter(group)
|
63
|
+
Acts::DataTable.lookup_nested_hash(active_filters, group.to_s).try(:keys).try(:first)
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Adds a new filter to the current controller action
|
68
|
+
# Before the filter is added, the following things are checked to ensure
|
69
|
+
# that no invalid filter is added (which could cause reoccurring errors in the application)
|
70
|
+
#
|
71
|
+
# 1. The given +scope+ has to be registered in the currently used model
|
72
|
+
# 2. The given arguments have to be sufficient for the given +scope+
|
73
|
+
# 3. The +scope+ has to pass the set up validation check
|
74
|
+
#
|
75
|
+
# @param [String] group
|
76
|
+
# The group the given +scope+ is part of in the current #model
|
77
|
+
#
|
78
|
+
# @param [String] scope
|
79
|
+
# The scope name within +group+ and #model
|
80
|
+
#
|
81
|
+
# @param [Hash] args
|
82
|
+
# Arguments to be passed to the scope. They have to be in the format
|
83
|
+
# {arg_name => arg_value} as set up in the model. This is necessary
|
84
|
+
# to make validations as easy as possible.
|
85
|
+
#
|
86
|
+
def add_filter(group, scope, args)
|
87
|
+
reset_errors!
|
88
|
+
|
89
|
+
#Ensure that the argument hash is set properly. The following methods
|
90
|
+
#might fail for filters which do not require arguments otherwise.
|
91
|
+
args = {} unless args.is_a?(Hash)
|
92
|
+
|
93
|
+
#Check whether the given filter was registered properly in the model
|
94
|
+
unless Acts::DataTable::ScopeFilters::ActiveRecord.registered_filter?(model, group, scope)
|
95
|
+
add_error group, Acts::DataTable.t('scope_filters.add_filter.filter_not_registered', :model => model.name, :group => group, :scope_name => scope)
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
|
99
|
+
#Check whether the given arguments are sufficient for the given filter
|
100
|
+
unless Acts::DataTable::ScopeFilters::ActiveRecord.matching_arity?(model, group, scope, args.size)
|
101
|
+
add_error group, Acts::DataTable.t('scope_filters.add_filter.non_matching_arity', :model => model.name, :group => group, :scope_name => scope)
|
102
|
+
return false
|
103
|
+
end
|
104
|
+
|
105
|
+
#Run possible validation methods on the given filter and add generated error messages
|
106
|
+
if (errors = Acts::DataTable::ScopeFilters::Validator.new(model, group, scope, args).validate).any?
|
107
|
+
errors.each {|e| add_error(group, e)}
|
108
|
+
return false
|
109
|
+
end
|
110
|
+
|
111
|
+
#Add the new filter to the session
|
112
|
+
current_action_session[group.to_s] = {scope.to_s => args.stringify_keys}
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Removes the given filter group from the current controller action
|
118
|
+
# It is sufficient to only specify the group here as only one filter in a group
|
119
|
+
# may be active at a time.
|
120
|
+
#
|
121
|
+
def remove_filter!(group)
|
122
|
+
current_action_session.delete(group.to_s)
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# Resets all filters for the current controller action
|
127
|
+
#
|
128
|
+
def remove_all_filters!
|
129
|
+
sf_session[current_action_key] = {}
|
130
|
+
end
|
131
|
+
|
132
|
+
#----------------------------------------------------------------
|
133
|
+
# Sortable Columns
|
134
|
+
#----------------------------------------------------------------
|
135
|
+
|
136
|
+
#
|
137
|
+
# @return [Array] The sorting columns for the current request
|
138
|
+
# (controller + action) in the format [['col1', 'dir1'], ['col2', 'dir2'], ...]
|
139
|
+
#
|
140
|
+
# If no columns are set, the given default ones are used.
|
141
|
+
#
|
142
|
+
def active_columns
|
143
|
+
current_action_session(sc_session, [])
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
# Adds or removes a column from the current sorting columns
|
148
|
+
# This happens whenever the user decides to sort a table by multiple columns
|
149
|
+
#
|
150
|
+
def toggle_column!(model_name, column_name)
|
151
|
+
if active_column?(model_name, column_name)
|
152
|
+
remove_column!(model_name, column_name)
|
153
|
+
else
|
154
|
+
add_column!(model_name, column_name)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# Changes the sorting direction for the given column
|
160
|
+
# If no direction is given, it will change it to the opposite of the current direction
|
161
|
+
#
|
162
|
+
def change_direction!(model_name, column_name, direction = nil)
|
163
|
+
if active_column?(model_name, column_name)
|
164
|
+
ca = column_array(model_name, column_name)
|
165
|
+
ca[1] = (direction || opposite_direction(ca.last)).to_s.upcase
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# Replaces all current sorting columns with the given one
|
171
|
+
#
|
172
|
+
def set_base_column!(model, column, direction = nil)
|
173
|
+
reset_columns!
|
174
|
+
add_column!(model, column, direction)
|
175
|
+
end
|
176
|
+
|
177
|
+
#
|
178
|
+
# Sets all sorting columns for the current controller action at once.
|
179
|
+
# This can be used when supplying the user with a form to choose
|
180
|
+
# the sorting in a separate area of the page instead of clicking
|
181
|
+
# on table column headers and adding one column after the other
|
182
|
+
#
|
183
|
+
# @param [Array<String>] columns
|
184
|
+
# A 2D array of the form [['model_name', 'column_name', 'direction'], ...]
|
185
|
+
#
|
186
|
+
def set_columns!(columns)
|
187
|
+
reset_columns!
|
188
|
+
columns.each do |model, column, direction|
|
189
|
+
add_column!(model, column, direction)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
#
|
194
|
+
# Retrieves the current sorting direction for a given column.
|
195
|
+
#
|
196
|
+
# @return [String, NilClass] 'ASC' or 'DESC' if the given column
|
197
|
+
# is currently active, +nil+ otherwise
|
198
|
+
#
|
199
|
+
def sorting_direction(model_name, column_name)
|
200
|
+
column_array(model_name, column_name).try(:last)
|
201
|
+
end
|
202
|
+
|
203
|
+
#
|
204
|
+
# @return [TrueClass, FalseClass] +true+ if the given column is currently
|
205
|
+
# used for sorting
|
206
|
+
#
|
207
|
+
def active_column?(model_name, column_name)
|
208
|
+
!!column_array(model_name, column_name)
|
209
|
+
end
|
210
|
+
|
211
|
+
private
|
212
|
+
|
213
|
+
#
|
214
|
+
# Removes all current sorting columns
|
215
|
+
#
|
216
|
+
def reset_columns!
|
217
|
+
sc_session[current_action_key] = []
|
218
|
+
end
|
219
|
+
|
220
|
+
#
|
221
|
+
# @return [String] the opposite direction to the given one
|
222
|
+
#
|
223
|
+
def opposite_direction(direction)
|
224
|
+
direction.downcase == 'asc' ? 'DESC' : 'ASC'
|
225
|
+
end
|
226
|
+
|
227
|
+
#
|
228
|
+
# Removes the given column from the current sorting
|
229
|
+
#
|
230
|
+
def remove_column!(model_name, column_name)
|
231
|
+
current_action_session(sc_session, []).delete(column_array(model_name, column_name))
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
# Adds the given column to the current sorting
|
236
|
+
#
|
237
|
+
def add_column!(model_name, column_name, direction = nil)
|
238
|
+
direction ||= 'ASC'
|
239
|
+
d = column_data(model_name, column_name)
|
240
|
+
current_action_session(sc_session, []).push([d[:column], direction.to_s.upcase])
|
241
|
+
end
|
242
|
+
|
243
|
+
#
|
244
|
+
# Retrieves the array consisting of column name and direction from the session
|
245
|
+
#
|
246
|
+
# @return [Array, NilClass] Either an array of the form ['table.column', 'direction']
|
247
|
+
# or +nil+ if the given column is not part of the current sorting
|
248
|
+
#
|
249
|
+
def column_array(model_name, column_name)
|
250
|
+
current_action_session(sc_session, []).assoc(column_data(model_name, column_name)[:column])
|
251
|
+
end
|
252
|
+
|
253
|
+
#
|
254
|
+
# @return [ActiveRecord::Base] The constantized model
|
255
|
+
#
|
256
|
+
def get_model(model_name)
|
257
|
+
model_name.to_s.camelize.constantize
|
258
|
+
end
|
259
|
+
|
260
|
+
#
|
261
|
+
# @return [Hash] The constantized model and column name with table prefix
|
262
|
+
#
|
263
|
+
def column_data(model_name, column_name)
|
264
|
+
m = get_model(model_name)
|
265
|
+
column = "#{m.table_name}.#{column_name}"
|
266
|
+
{:model => m, :column => column}
|
267
|
+
end
|
268
|
+
|
269
|
+
def current_action_session(s = sf_session, default = {})
|
270
|
+
s[current_action_key] ||= default
|
271
|
+
end
|
272
|
+
|
273
|
+
#
|
274
|
+
# Clears old error messages. This is useful whenever only error messages from
|
275
|
+
# a current action should be retrieved.
|
276
|
+
#
|
277
|
+
def reset_errors!
|
278
|
+
@errors = {}
|
279
|
+
end
|
280
|
+
|
281
|
+
#
|
282
|
+
# Adds an error message to the errors array
|
283
|
+
#
|
284
|
+
# @param [String] context
|
285
|
+
# Context the error occurred in, e.g. a scope filter group
|
286
|
+
#
|
287
|
+
# @param [String] message
|
288
|
+
# The error message to be added.
|
289
|
+
#
|
290
|
+
def add_error(context, message)
|
291
|
+
errors[context.to_s] ||= []
|
292
|
+
errors[context.to_s] << message
|
293
|
+
end
|
294
|
+
|
295
|
+
#
|
296
|
+
# Generates a key from the given controller and action name
|
297
|
+
#
|
298
|
+
def action_key(controller, action)
|
299
|
+
[controller.gsub('/', '_'), action].join('_')
|
300
|
+
end
|
301
|
+
|
302
|
+
#
|
303
|
+
# @see #action_key, uses the current controller path and action name
|
304
|
+
#
|
305
|
+
def current_action_key
|
306
|
+
action_key(@controller_path, @action_name)
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Acts
|
2
|
+
module DataTable
|
3
|
+
module SortableColumns
|
4
|
+
module ActionController
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
#
|
12
|
+
# Sets up automatic column sorting for this controller
|
13
|
+
#
|
14
|
+
# @param [Hash] options
|
15
|
+
# Options to specify which controller actions should have column sorting
|
16
|
+
# and to customize the filter's behaviour.
|
17
|
+
# Options are everything that #around_filter would accept
|
18
|
+
#
|
19
|
+
# @option options [Hash] :default
|
20
|
+
# Default sorting columns for different actions.
|
21
|
+
# If none are specified for an action, the default order (usually 'id ASC') is used
|
22
|
+
#
|
23
|
+
# @example Set up automatic column sorting only for the index action
|
24
|
+
# with the default ordering "deleted_at ASC, name ASC"
|
25
|
+
#
|
26
|
+
# sortable_columns :only => [:index], :default => {:index => [['deleted_at', 'ASC'], ['name', 'ASC']]}
|
27
|
+
#
|
28
|
+
def sortable_columns(options = {})
|
29
|
+
#Include on-demand methods
|
30
|
+
include Acts::DataTable::Shared::ActionController::OnDemand
|
31
|
+
|
32
|
+
defaults = (options.delete(:default) || {}).stringify_keys
|
33
|
+
|
34
|
+
around_filter(options) do |controller, block|
|
35
|
+
|
36
|
+
af_params = controller.request.params[:sortable_columns]
|
37
|
+
request_defaults = defaults[controller.action_name.to_s] || []
|
38
|
+
|
39
|
+
begin
|
40
|
+
#Ensure that the given action is valid
|
41
|
+
if af_params.present? && %w(toggle change_direction set_base set).include?(af_params[:action].to_s)
|
42
|
+
case af_action = af_params[:action].to_s
|
43
|
+
when 'toggle'
|
44
|
+
controller.acts_as_data_table_session.toggle_column!(af_params[:model], af_params[:column])
|
45
|
+
when 'change_direction'
|
46
|
+
controller.acts_as_data_table_session.change_direction!(af_params[:model], af_params[:column])
|
47
|
+
when 'set_base'
|
48
|
+
controller.acts_as_data_table_session.set_base_column!(af_params[:model], af_params[:column])
|
49
|
+
when 'set'
|
50
|
+
controller.acts_as_data_table_session.set_columns!(af_params[:columns])
|
51
|
+
else
|
52
|
+
raise ArgumentError.new "Invalid scope filter action '#{af_action}' was given."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#Set the defaults as sorting columns none were set by the user
|
57
|
+
if controller.acts_as_data_table_session.active_columns.empty?
|
58
|
+
controller.acts_as_data_table_session.set_columns!(request_defaults)
|
59
|
+
end
|
60
|
+
|
61
|
+
#Set the updated filters
|
62
|
+
Acts::DataTable::SortableColumns::ActionController.set_request_sort_columns!(controller.acts_as_data_table_session.active_columns)
|
63
|
+
block.call
|
64
|
+
ensure
|
65
|
+
Acts::DataTable::SortableColumns::ActionController.clear_request_sort_columns!
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Returns the currently active sortable columns.
|
74
|
+
# This function should only be used when the automatic scope +with_sortable_columns+
|
75
|
+
# is not working due to a different execution time or thread, e.g. a background worker.
|
76
|
+
#
|
77
|
+
def current_sortable_columns
|
78
|
+
Acts::DataTable::SortableColumns::ActionController.get_request_sort_columns
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Retrieves the columns to order by for the current request from the thread space. This is used in the
|
83
|
+
# model's scope, so no string has to be supplied in the controller action manually.
|
84
|
+
#
|
85
|
+
# @return [Array<String>] the columns and their sorting directions in the format
|
86
|
+
# [["col1", "dir1"], ["col2", "dir2"], ...]
|
87
|
+
#
|
88
|
+
def self.get_request_sort_columns
|
89
|
+
Thread.current[:sortable_columns] || []
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Sets the columns to order by for the current request
|
94
|
+
# in the thread space
|
95
|
+
#
|
96
|
+
# @param [Array<String>] columns
|
97
|
+
#
|
98
|
+
def self.set_request_sort_columns!(columns)
|
99
|
+
Thread.current[:sortable_columns] = columns
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Deletes the current sort columns from the thread space
|
104
|
+
#
|
105
|
+
def self.clear_request_sort_columns!
|
106
|
+
Thread.current[:sortable_columns] = nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Acts
|
2
|
+
module DataTable
|
3
|
+
module SortableColumns
|
4
|
+
module ActiveRecord
|
5
|
+
def self.included(base)
|
6
|
+
|
7
|
+
#
|
8
|
+
# Scope which applies the currently active sorting directions.
|
9
|
+
# The sorting columns are automatically fetched from the current thread space,
|
10
|
+
# however, it is also possible to pass these values in as first argument.
|
11
|
+
# This should only be done if absolutely necessary, e.g. if
|
12
|
+
# the calculation happens in a different time or thread as it would in a
|
13
|
+
# background calculation.
|
14
|
+
#
|
15
|
+
base.named_scope :with_sortable_columns, lambda {|*args|
|
16
|
+
sort_columns = args.first
|
17
|
+
sort_columns ||= Acts::DataTable::SortableColumns::ActionController.get_request_sort_columns
|
18
|
+
|
19
|
+
if sort_columns.any?
|
20
|
+
sort_string = sort_columns.map {|col, dir| "#{col} #{dir}"}.join(', ')
|
21
|
+
{:order => sort_string}
|
22
|
+
else
|
23
|
+
{}
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Acts
|
2
|
+
module DataTable
|
3
|
+
module SortableColumns
|
4
|
+
module Renderers
|
5
|
+
class Bootstrap2 < Default
|
6
|
+
def direction_indicator
|
7
|
+
if @sortable.direction == 'ASC'
|
8
|
+
@action_view.content_tag(:i, nil, :class => 'icon-sort-by-alphabet')
|
9
|
+
else
|
10
|
+
@action_view.content_tag(:i, nil, :class => 'icon-sort-by-alphabet-alt')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#
|
2
|
+
# Default renderer for ActsAsDataTable sortable column links.
|
3
|
+
# It uses the javascript library shipped with the gem and does not depend on
|
4
|
+
# external sources like javascripts or additional stylesheets.
|
5
|
+
#
|
6
|
+
module Acts
|
7
|
+
module DataTable
|
8
|
+
module SortableColumns
|
9
|
+
module Renderers
|
10
|
+
def self.default_renderer
|
11
|
+
@@default_renderer ||= 'Acts::DataTable::SortableColumns::Renderers::Default'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.default_renderer=(renderer)
|
15
|
+
@@default_renderer = renderer.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
class Default
|
19
|
+
def initialize(sortable, action_view)
|
20
|
+
@action_view = action_view
|
21
|
+
@sortable = sortable
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# @return [String] an indicator about the sorting direction for the current column.
|
26
|
+
# The direction is either 'ASC' or 'DESC'
|
27
|
+
#
|
28
|
+
def direction_indicator
|
29
|
+
@sortable.direction == 'ASC' ? 'Δ' : '∇'
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# @return [String] The column header's caption
|
34
|
+
#
|
35
|
+
def caption
|
36
|
+
@sortable.caption
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# @return [String] a link to change the sorting direction for an already active column
|
41
|
+
#
|
42
|
+
def direction_link
|
43
|
+
link_options = @sortable.html_options.clone
|
44
|
+
link_options['data-init'] = 'sortable-column-direction'
|
45
|
+
link_options['data-remote'] = @sortable.remote
|
46
|
+
link_options['data-url-change-direction'] = @sortable.urls.change_direction
|
47
|
+
@action_view.link_to(direction_indicator, '#', link_options)
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# @return [String] a link to toggle a column
|
52
|
+
#
|
53
|
+
def caption_link
|
54
|
+
link_options = @sortable.html_options.clone
|
55
|
+
link_options['data-init'] = 'sortable-column'
|
56
|
+
link_options['data-remote'] = @sortable.remote
|
57
|
+
link_options['data-url-toggle'] = @sortable.urls.toggle
|
58
|
+
link_options['data-url-set-base'] = @sortable.urls.set_base
|
59
|
+
link_options['data-url-change-direction'] = @sortable.urls.change_direction
|
60
|
+
link_options['data-active'] = 'true' if @sortable.active
|
61
|
+
|
62
|
+
@action_view.link_to(@sortable.caption, '#', link_options)
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Generates the actual HTML (= caption and direction links)
|
67
|
+
# to be embedded into the view
|
68
|
+
#
|
69
|
+
# @return [String] the generated HTML code
|
70
|
+
#
|
71
|
+
def to_html
|
72
|
+
if @sortable.active
|
73
|
+
caption_link + ' ' + direction_link
|
74
|
+
else
|
75
|
+
caption_link
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'acts_as_data_table/version'
|
2
|
+
|
3
|
+
require 'acts_as_data_table/multi_column_scopes'
|
4
|
+
|
5
|
+
require 'acts_as_data_table/shared/session'
|
6
|
+
require 'acts_as_data_table/shared/action_controller'
|
7
|
+
|
8
|
+
require 'acts_as_data_table/scope_filters/action_controller'
|
9
|
+
require 'acts_as_data_table/scope_filters/active_record'
|
10
|
+
require 'acts_as_data_table/scope_filters/validator'
|
11
|
+
|
12
|
+
require 'acts_as_data_table/sortable_columns/action_controller'
|
13
|
+
require 'acts_as_data_table/sortable_columns/active_record'
|
14
|
+
require 'acts_as_data_table/scope_filters/form_helper'
|
15
|
+
|
16
|
+
#Sortable Column Renderers
|
17
|
+
require 'acts_as_data_table/sortable_columns/renderers/default'
|
18
|
+
require 'acts_as_data_table/sortable_columns/renderers/bootstrap2'
|
19
|
+
|
20
|
+
module ActsAsDataTable
|
21
|
+
end
|
22
|
+
|
23
|
+
module Acts
|
24
|
+
module DataTable
|
25
|
+
I18n_LOCALES = %w(en)
|
26
|
+
|
27
|
+
def self.log(level, message)
|
28
|
+
Rails.logger.send(level, "Acts::DataTable [#{level}] -- #{message}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.ensure_nested_hash!(hash, *keys)
|
32
|
+
h = hash
|
33
|
+
keys.each do |key|
|
34
|
+
h[key] ||= {}
|
35
|
+
h = h[key]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.lookup_nested_hash(hash, *keys)
|
40
|
+
return nil if hash.nil?
|
41
|
+
|
42
|
+
h = hash
|
43
|
+
keys.each do |key|
|
44
|
+
return nil if h[key].nil?
|
45
|
+
h = h[key]
|
46
|
+
end
|
47
|
+
h
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Retrieves a value from the gem's locale namespace.
|
52
|
+
# If there are no translations for the application's locale, the
|
53
|
+
# english versions are used.
|
54
|
+
#
|
55
|
+
def self.t(key, options = {})
|
56
|
+
locale = I18n_LOCALES.include?(I18n.locale.to_s) ? I18n.locale : 'en'
|
57
|
+
I18n.t(key, options.merge({:scope => 'acts_as_data_table', :locale => locale}))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
ActiveRecord::Base.class_eval do
|
63
|
+
include Acts::DataTable::MultiColumnScopes
|
64
|
+
include Acts::DataTable::ScopeFilters::ActiveRecord
|
65
|
+
include Acts::DataTable::SortableColumns::ActiveRecord
|
66
|
+
end
|
67
|
+
|
68
|
+
ActionController::Base.class_eval do
|
69
|
+
include Acts::DataTable::ScopeFilters::ActionController
|
70
|
+
include Acts::DataTable::SortableColumns::ActionController
|
71
|
+
end
|