effective_datatables 2.0.1 → 2.0.2
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee.erb +19 -5
- data/app/controllers/effective/datatables_controller.rb +1 -1
- data/app/helpers/effective_datatables_helper.rb +7 -2
- data/app/models/effective/active_record_datatable_tool.rb +16 -0
- data/app/models/effective/effective_datatable/ajax.rb +5 -6
- data/app/models/effective/effective_datatable/options.rb +40 -13
- data/app/models/effective/effective_datatable/rendering.rb +10 -16
- data/lib/effective_datatables/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb195f3890afb3faee956495d534e0a1bb09013e
|
4
|
+
data.tar.gz: 8acf1b7ec6a347a3157718504f6830a001d0360c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8cb8fc4dbb8f209bd2a5259e5c0f1594a5c1bb0a8dc763cbd0ae55b63b8194bb5ca96649fd0fbf5b4b97b6bec8cbc06fa8da7144e04d67aeb1c49fce52accfa
|
7
|
+
data.tar.gz: 4d9addc52f7eac6742137e29a967aa465a69bd2c4baadcbebbb248b6dcedf6eab3457819e8002447aaf729a59d1a631232ea646ec484bd4fbabd63ae9acd63e3
|
@@ -20,18 +20,30 @@ initializeDataTables = ->
|
|
20
20
|
{ sortable: false, targets: datatable.data('non-sortable') }
|
21
21
|
].concat(datatable.data('column-classes') || []).concat(datatable.data('column-names') || [])
|
22
22
|
order: datatable.data('default-order')
|
23
|
+
serverParams: (params) ->
|
24
|
+
table = this.DataTable()
|
25
|
+
table.columns().flatten().each (index) => # Pass which columns are visible back to server
|
26
|
+
params['columns'][index]['visible'] = table.column(index).visible()
|
23
27
|
colVis:
|
24
28
|
showAll: 'Show all'
|
25
29
|
restore: 'Show default'
|
26
30
|
activate: 'click'
|
27
31
|
align: 'right'
|
28
32
|
label: (index, title, th) -> $(th).prop('title')
|
33
|
+
stateChange: (iCol, bVisible) ->
|
34
|
+
timeout = $(this.dom.button).data('timeout')
|
35
|
+
clearTimeout(timeout) if timeout
|
36
|
+
timeout = setTimeout(
|
37
|
+
=>
|
38
|
+
$(this.dom.button).closest('.dataTables_wrapper').find('table').first().DataTable().draw()
|
39
|
+
$.event.trigger('page:change')
|
40
|
+
, 1000)
|
41
|
+
$(this.dom.button).data('timeout', timeout)
|
29
42
|
tableTools:
|
30
43
|
sSwfPath: "<%= asset_path('effective_datatables/copy_csv_xls_pdf.swf') %>",
|
31
44
|
aButtons: ['csv', {'sExtends': 'xls', 'sButtonText': 'Excel'}, 'print']
|
32
45
|
|
33
|
-
|
34
|
-
if simple
|
46
|
+
if datatable.data('effective-datatables-table') == 'simple'
|
35
47
|
init_options['lengthMenu'] = [-1] # Show all results
|
36
48
|
init_options['dom'] = "<'row'r>t" # Just show the table
|
37
49
|
|
@@ -46,12 +58,14 @@ initializeDataTables = ->
|
|
46
58
|
table.DataTable().column("#{obj.data('column-name')}:name").search(obj.val()).draw()
|
47
59
|
|
48
60
|
# For every existing Input, Set up the search events
|
49
|
-
|
61
|
+
search_inputs = datatable.find('thead').first().find('input,select')
|
62
|
+
|
63
|
+
search_inputs.each (index, input) ->
|
50
64
|
$input = $(input)
|
51
65
|
|
52
66
|
if $input.data('column-name')
|
53
|
-
$input.on 'click', (event) -> false # Dont order columns when you click inside the input
|
54
|
-
$input.on 'mousedown', (event) -> event.stopPropagation() # Dont order columns when you click inside the input
|
67
|
+
$input.parent().on 'click', (event) -> false # Dont order columns when you click inside the input
|
68
|
+
$input.parent().on 'mousedown', (event) -> event.stopPropagation() # Dont order columns when you click inside the input
|
55
69
|
|
56
70
|
if $input.is('select')
|
57
71
|
$input.on 'change', (event) -> dataTableSearch(event)
|
@@ -31,8 +31,13 @@ module EffectiveDatatablesHelper
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
form.input name, label: false, required: false,
|
35
|
-
|
34
|
+
form.input name, label: false, required: false,
|
35
|
+
as: (defined?(EffectiveFormInputs) ? :effective_select : :select),
|
36
|
+
collection: opts[:filter][:values],
|
37
|
+
multiple: opts[:filter][:multiple] == true,
|
38
|
+
include_blank: (opts[:label] || name.titleize),
|
39
|
+
input_html: { name: nil, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} },
|
40
|
+
input_js: { placeholder: (opts[:label] || name.titleize) }
|
36
41
|
else
|
37
42
|
content_tag(:p, opts[:label] || name)
|
38
43
|
end
|
@@ -46,6 +46,22 @@ module Effective
|
|
46
46
|
else
|
47
47
|
collection.where("#{column} ILIKE :term", term: "%#{term}%")
|
48
48
|
end
|
49
|
+
when :has_many
|
50
|
+
inverse_ids = term.split(',').map { |term| (term = term.to_i) == 0 ? nil : term }.compact
|
51
|
+
return collection unless inverse_ids.present?
|
52
|
+
|
53
|
+
reflection = collection.klass.reflect_on_association(table_column[:name].to_sym)
|
54
|
+
raise "unable to find #{collection.klass.name} :has_many :#{table_column[:name]} association" unless reflection
|
55
|
+
|
56
|
+
obj = reflection.build_association({}) # Clinic
|
57
|
+
klass = obj.class
|
58
|
+
|
59
|
+
inverse = klass.reflect_on_association(collection.table_name) || obj.class.reflect_on_association(collection.table_name.singularize)
|
60
|
+
raise "unable to find #{klass.name} has_many :#{collection.table_name} or belongs_to :#{collection.table_name.singularize} associations" unless inverse
|
61
|
+
|
62
|
+
ids = klass.where(id: inverse_ids).joins(inverse.name).pluck(inverse.foreign_key)
|
63
|
+
|
64
|
+
collection.where(id: ids)
|
49
65
|
when :datetime, :date
|
50
66
|
begin
|
51
67
|
digits = term.scan(/(\d+)/).flatten.map(&:to_i)
|
@@ -8,12 +8,11 @@ module Effective
|
|
8
8
|
# It sends us a list of columns that are different than our table_columns order
|
9
9
|
# So this method just returns an array of column names, as per ColReorder
|
10
10
|
def display_table_columns
|
11
|
-
if params[:columns].
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
11
|
+
return nil if params[:columns].blank?
|
12
|
+
|
13
|
+
@display_table_columns ||= params[:columns].each_with_object({}) do |(_, column), retval|
|
14
|
+
retval[column[:name]] = table_columns[column[:name]] # Same order as ColReordernow
|
15
|
+
retval[column[:name]][:visible] = (column[:visible] == 'true') # As per ColVis
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
@@ -15,20 +15,22 @@ module Effective
|
|
15
15
|
|
16
16
|
# Here we identify all belongs_to associations and build up a Hash like:
|
17
17
|
# {user: {foreign_key: 'user_id', klass: User}, order: {foreign_key: 'order_id', klass: Effective::Order}}
|
18
|
-
belong_tos = (collection.
|
19
|
-
|
20
|
-
begin
|
21
|
-
klass = bt.klass || bt.foreign_type.sub('_type', '').classify.constantize
|
22
|
-
rescue => e
|
23
|
-
klass = nil
|
24
|
-
end
|
18
|
+
belong_tos = (collection.klass.reflect_on_all_associations(:belongs_to) rescue []).inject({}) do |retval, bt|
|
19
|
+
next if bt.options[:polymorphic]
|
25
20
|
|
26
|
-
|
27
|
-
|
21
|
+
klass = bt.klass || (bt.foreign_type.sub('_type', '').classify.constantize rescue nil)
|
22
|
+
retval[bt.name.to_s] = {foreign_key: bt.foreign_key, klass: klass} if bt.foreign_key.present? && klass.present?
|
28
23
|
|
29
24
|
retval
|
30
25
|
end
|
31
26
|
|
27
|
+
# has_manys
|
28
|
+
has_manys = (collection.klass.reflect_on_all_associations(:has_many) rescue []).inject({}) do |retval, hm|
|
29
|
+
klass = hm.klass || (hm.build_association({}).class)
|
30
|
+
retval[hm.name.to_s] = {klass: klass}
|
31
|
+
retval
|
32
|
+
end
|
33
|
+
|
32
34
|
table_columns = cols.each_with_index do |(name, _), index|
|
33
35
|
# If this is a belongs_to, add an :if clause specifying a collection scope if
|
34
36
|
if belong_tos.key?(name)
|
@@ -45,10 +47,29 @@ module Effective
|
|
45
47
|
cols[name][:label] ||= name.titleize
|
46
48
|
cols[name][:column] ||= (sql_table && sql_column) ? "\"#{sql_table.name}\".\"#{sql_column.name}\"" : name
|
47
49
|
cols[name][:width] ||= nil
|
48
|
-
cols[name][:sortable] = true if cols[name][:sortable]
|
49
|
-
cols[name][:
|
50
|
+
cols[name][:sortable] = true if cols[name][:sortable].nil?
|
51
|
+
cols[name][:visible] = true if cols[name][:visible].nil?
|
52
|
+
|
53
|
+
# Type
|
54
|
+
cols[name][:type] ||= (
|
55
|
+
if belong_tos.key?(name)
|
56
|
+
:belongs_to
|
57
|
+
elsif has_manys.key?(name)
|
58
|
+
:has_many
|
59
|
+
elsif sql_column.try(:type).present?
|
60
|
+
sql_column.type
|
61
|
+
else
|
62
|
+
:string # When in doubt
|
63
|
+
end
|
64
|
+
)
|
65
|
+
|
50
66
|
cols[name][:class] = "col-#{cols[name][:type]} col-#{name} #{cols[name][:class]}".strip
|
51
67
|
|
68
|
+
# HasMany
|
69
|
+
if cols[name][:type] == :has_many
|
70
|
+
cols[name][:sortable] = false
|
71
|
+
end
|
72
|
+
|
52
73
|
# EffectiveObfuscation
|
53
74
|
if name == 'id' && defined?(EffectiveObfuscation) && collection.respond_to?(:deobfuscate)
|
54
75
|
cols[name][:sortable] = false
|
@@ -66,7 +87,7 @@ module Effective
|
|
66
87
|
cols[name][:sql_as_column] = true
|
67
88
|
end
|
68
89
|
|
69
|
-
cols[name][:filter] = initialize_table_column_filter(cols[name][:filter], cols[name][:type], belong_tos[name])
|
90
|
+
cols[name][:filter] = initialize_table_column_filter(cols[name][:filter], cols[name][:type], belong_tos[name], has_manys[name])
|
70
91
|
|
71
92
|
if cols[name][:partial]
|
72
93
|
cols[name][:partial_local] ||= (sql_table.try(:name) || cols[name][:partial].split('/').last(2).first.presence || 'obj').singularize.to_sym
|
@@ -81,7 +102,7 @@ module Effective
|
|
81
102
|
|
82
103
|
end
|
83
104
|
|
84
|
-
def initialize_table_column_filter(filter, col_type, belongs_to)
|
105
|
+
def initialize_table_column_filter(filter, col_type, belongs_to, has_many)
|
85
106
|
return {type: :null} if filter == false
|
86
107
|
|
87
108
|
filter = {type: filter.to_sym} if filter.kind_of?(String)
|
@@ -96,6 +117,12 @@ module Effective
|
|
96
117
|
type: :select,
|
97
118
|
values: Proc.new { belongs_to[:klass].all.map { |obj| [obj.to_s, obj.id] }.sort { |x, y| x[1] <=> y[1] } }
|
98
119
|
}
|
120
|
+
when :has_many
|
121
|
+
{
|
122
|
+
type: :select,
|
123
|
+
multiple: true,
|
124
|
+
values: Proc.new { has_many[:klass].all.map { |obj| [obj.to_s, obj.id] }.sort { |x, y| x[1] <=> y[1] } }
|
125
|
+
}
|
99
126
|
when :effective_roles
|
100
127
|
{type: :select, values: EffectiveRoles.roles}
|
101
128
|
when :integer
|
@@ -59,8 +59,8 @@ module Effective
|
|
59
59
|
|
60
60
|
# We want to use the render :collection for each column that renders partials
|
61
61
|
rendered = {}
|
62
|
-
table_columns.each do |name, opts|
|
63
|
-
if opts[:partial]
|
62
|
+
(display_table_columns || table_columns).each do |name, opts|
|
63
|
+
if opts[:partial] && opts[:visible]
|
64
64
|
locals = {
|
65
65
|
datatable: self,
|
66
66
|
table_column: table_columns[name],
|
@@ -84,14 +84,19 @@ module Effective
|
|
84
84
|
|
85
85
|
collection.each_with_index.map do |obj, index|
|
86
86
|
(display_table_columns || table_columns).map do |name, opts|
|
87
|
-
|
87
|
+
if opts[:visible] == false
|
88
|
+
''
|
89
|
+
elsif opts[:partial]
|
88
90
|
rendered[name][index]
|
89
91
|
elsif opts[:block]
|
90
92
|
view.instance_exec(obj, collection, self, &opts[:block])
|
91
93
|
elsif opts[:proc]
|
92
94
|
view.instance_exec(obj, collection, self, &opts[:proc])
|
93
95
|
elsif opts[:type] == :belongs_to
|
94
|
-
|
96
|
+
(obj.send(name) rescue nil).to_s
|
97
|
+
elsif opts[:type] == :has_many
|
98
|
+
objs = (obj.send(name).map(&:to_s).sort rescue [])
|
99
|
+
objs.length == 1 ? objs.first : (opts[:sentence] ? objs.to_sentence : objs.join('<br>'))
|
95
100
|
elsif opts[:type] == :obfuscated_id
|
96
101
|
(obj.send(:to_param) rescue nil).to_s
|
97
102
|
elsif opts[:type] == :effective_roles
|
@@ -101,20 +106,9 @@ module Effective
|
|
101
106
|
elsif opts[:type] == :date
|
102
107
|
(obj.send(name).strftime(EffectiveDatatables.date_format) rescue nil)
|
103
108
|
else
|
104
|
-
|
105
|
-
val = (obj[opts[:array_index]] rescue nil) if val == nil
|
106
|
-
val
|
109
|
+
obj.send(name) rescue (obj[opts[:array_index]] rescue nil)
|
107
110
|
end
|
108
111
|
|
109
|
-
# Last minute formatting of dates
|
110
|
-
case value
|
111
|
-
when Date
|
112
|
-
value.strftime(EffectiveDatatables.date_format)
|
113
|
-
when Time, DateTime
|
114
|
-
value.strftime(EffectiveDatatables.datetime_format)
|
115
|
-
else
|
116
|
-
value.to_s
|
117
|
-
end
|
118
112
|
end
|
119
113
|
end
|
120
114
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_datatables
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|