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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7bd5fa4ae2a9aa6654ae6341bc6e324741c0387
4
- data.tar.gz: b14fdda1521d4046ffc94aaf3fa173ab8d42863c
3
+ metadata.gz: eb195f3890afb3faee956495d534e0a1bb09013e
4
+ data.tar.gz: 8acf1b7ec6a347a3157718504f6830a001d0360c
5
5
  SHA512:
6
- metadata.gz: 83d1fbcad25d8ae5b780efbc70b61c9b8bb2fca94bff5397c640567663efa892a3d0f240f10fc7c15b1781935c7f45df0d45218e4d1abc2cdefc3dbe0dbc38a4
7
- data.tar.gz: 96e02057d1cd10ca8c57b8adc8d6b182b3ec291b91cefcc32e1fa6a2bb7382b1fbcd0f04759b2db9c457b1d7f8e9dad8540003bdfbd7e71b02fb9d80d1d245c2
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
- simple = datatable.data('effective-datatables-table') == 'simple'
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
- (search_inputs = datatable.find('thead').first().find('input,select')).each (index, input) ->
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)
@@ -1,6 +1,6 @@
1
1
  module Effective
2
2
  class DatatablesController < ApplicationController
3
- skip_log_page_views if defined?(EffectiveLogging)
3
+ skip_log_page_views quiet: true if defined?(EffectiveLogging)
4
4
 
5
5
  # This will respond to both a GET and a POST
6
6
  def show
@@ -31,8 +31,13 @@ module EffectiveDatatablesHelper
31
31
  end
32
32
  end
33
33
 
34
- form.input name, label: false, required: false, as: :select, collection: opts[:filter][:values], include_blank: (opts[:label] || name.titleize),
35
- input_html: { name: nil, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} }
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].present?
12
- HashWithIndifferentAccess.new().tap do |display_columns|
13
- params[:columns].each do |_, values|
14
- display_columns[values[:name]] = table_columns[values[:name]]
15
- end
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.ancestors.first.reflect_on_all_associations(:belongs_to) rescue []).inject(HashWithIndifferentAccess.new()) do |retval, bt|
19
- unless bt.options[:polymorphic]
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
- retval[bt.name] = {foreign_key: bt.foreign_key, klass: klass} if bt.foreign_key.present? && klass.present?
27
- end
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] == nil
49
- cols[name][:type] ||= (belong_tos.key?(name) ? :belongs_to : sql_column.try(:type).presence) || :string
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
- value = if opts[:partial]
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
- val = (obj.send(name) rescue nil).to_s
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
- val = (obj.send(name) rescue nil)
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
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '2.0.1'.freeze
2
+ VERSION = '2.0.2'.freeze
3
3
  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.1
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-07-24 00:00:00.000000000 Z
11
+ date: 2015-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails