tabulatr2 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +71 -27
  4. data/app/assets/javascripts/tabulatr/application.js +130 -133
  5. data/app/assets/stylesheets/tabulatr/application.css.scss +153 -0
  6. data/app/assets/stylesheets/tabulatr/bootstrap2_fixes.css.scss +24 -0
  7. data/app/views/tabulatr/_tabulatr_actual_table.html.slim +35 -0
  8. data/app/views/tabulatr/_tabulatr_batch_actions_menu.html.slim +34 -0
  9. data/app/views/tabulatr/_tabulatr_filter_dialog.html.slim +84 -0
  10. data/app/views/tabulatr/_tabulatr_filter_menu.html.slim +30 -0
  11. data/app/views/tabulatr/_tabulatr_fuzzy_search_field.html.slim +24 -0
  12. data/app/views/tabulatr/_tabulatr_info_string.html.slim +23 -0
  13. data/app/views/tabulatr/_tabulatr_paginator.html.slim +24 -0
  14. data/app/views/tabulatr/_tabulatr_static_table.html.slim +33 -0
  15. data/app/views/tabulatr/_tabulatr_table.html.slim +45 -0
  16. data/lib/tabulatr/data/column_name_builder.rb +86 -0
  17. data/lib/tabulatr/data/data.rb +135 -0
  18. data/lib/tabulatr/data/dsl.rb +61 -0
  19. data/lib/tabulatr/data/filtering.rb +101 -0
  20. data/lib/tabulatr/data/formatting.rb +65 -0
  21. data/lib/tabulatr/data/invoker.rb +37 -0
  22. data/lib/tabulatr/data/pagination.rb +48 -0
  23. data/lib/tabulatr/data/proxy.rb +41 -0
  24. data/lib/tabulatr/{tabulatr/batch_actions.rb → data/sorting.rb} +20 -23
  25. data/lib/tabulatr/engine.rb +24 -1
  26. data/lib/tabulatr/generators/railtie.rb +33 -0
  27. data/lib/tabulatr/generators/resource_override.rb +35 -0
  28. data/lib/{generators → tabulatr/generators}/tabulatr/install_generator.rb +21 -3
  29. data/lib/{generators → tabulatr/generators}/tabulatr/templates/tabulatr.yml +3 -1
  30. data/lib/tabulatr/generators/tabulatr/templates/tabulatr_data.rb +18 -0
  31. data/lib/tabulatr/json_builder.rb +94 -0
  32. data/lib/tabulatr/rails/action_controller.rb +36 -0
  33. data/lib/{initializers → tabulatr/rails}/action_view.rb +6 -3
  34. data/lib/{initializers → tabulatr/rails}/active_record.rb +11 -19
  35. data/lib/tabulatr/renderer/action.rb +32 -0
  36. data/lib/tabulatr/{tabulatr/formattr.rb → renderer/association.rb} +19 -30
  37. data/lib/tabulatr/renderer/checkbox.rb +36 -0
  38. data/lib/tabulatr/renderer/column.rb +113 -0
  39. data/lib/{initializers/mark_as_localizable.rb → tabulatr/renderer/columns.rb} +13 -15
  40. data/lib/tabulatr/renderer/columns_from_block.rb +56 -0
  41. data/lib/tabulatr/renderer/renderer.rb +96 -0
  42. data/lib/tabulatr/utility/utility.rb +46 -0
  43. data/lib/tabulatr/version.rb +25 -2
  44. data/lib/tabulatr.rb +45 -4
  45. data/lib/tabulatr2.rb +1 -0
  46. data/spec/dummy/app/assets/stylesheets/application.css.scss +2 -2
  47. data/spec/dummy/app/controllers/products_controller.rb +27 -3
  48. data/spec/dummy/app/models/vendor.rb +1 -0
  49. data/spec/dummy/app/tabulatr_data/product_tabulatr_data.rb +29 -0
  50. data/spec/dummy/app/views/products/implicit_columns.html.erb +1 -0
  51. data/spec/dummy/app/views/products/one_item_per_page.html.erb +1 -1
  52. data/spec/dummy/app/views/products/simple_index.html.erb +6 -4
  53. data/spec/dummy/app/views/products/stupid_array.html.erb +1 -1
  54. data/spec/dummy/app/views/products/with_batch_actions.html.erb +10 -0
  55. data/spec/dummy/config/locales/tabulatr.yml +22 -1
  56. data/spec/dummy/config/routes.rb +3 -1
  57. data/spec/features/tabulatrs_spec.rb +53 -11
  58. data/tabulatr.gemspec +1 -1
  59. metadata +50 -42
  60. data/app/assets/images/tabulatr/buttons_lite_background.png +0 -0
  61. data/app/assets/images/tabulatr/pager_arrow_left.gif +0 -0
  62. data/app/assets/images/tabulatr/pager_arrow_left_off.gif +0 -0
  63. data/app/assets/images/tabulatr/pager_arrow_right.gif +0 -0
  64. data/app/assets/images/tabulatr/pager_arrow_right_off.gif +0 -0
  65. data/app/assets/images/tabulatr/sort_arrow_down.gif +0 -0
  66. data/app/assets/images/tabulatr/sort_arrow_down_off.gif +0 -0
  67. data/app/assets/images/tabulatr/sort_arrow_up.gif +0 -0
  68. data/app/assets/images/tabulatr/sort_arrow_up_off.gif +0 -0
  69. data/app/assets/stylesheets/tabulatr/application.css +0 -40
  70. data/lib/initializers/action_controller.rb +0 -13
  71. data/lib/tabulatr/tabulatr/adapter/active_record.rb +0 -84
  72. data/lib/tabulatr/tabulatr/adapter.rb +0 -55
  73. data/lib/tabulatr/tabulatr/data_cell.rb +0 -132
  74. data/lib/tabulatr/tabulatr/dummy_record.rb +0 -40
  75. data/lib/tabulatr/tabulatr/empty_cell.rb +0 -44
  76. data/lib/tabulatr/tabulatr/filter_cell.rb +0 -145
  77. data/lib/tabulatr/tabulatr/filter_icon.rb +0 -6
  78. data/lib/tabulatr/tabulatr/finder/find_for_table.rb +0 -187
  79. data/lib/tabulatr/tabulatr/finder.rb +0 -64
  80. data/lib/tabulatr/tabulatr/header_cell.rb +0 -146
  81. data/lib/tabulatr/tabulatr/json_builder.rb +0 -57
  82. data/lib/tabulatr/tabulatr/paginator.rb +0 -76
  83. data/lib/tabulatr/tabulatr/row_builder.rb +0 -128
  84. data/lib/tabulatr/tabulatr/security.rb +0 -21
  85. data/lib/tabulatr/tabulatr/settings.rb +0 -158
  86. data/lib/tabulatr/tabulatr.rb +0 -343
  87. data/spec/lib/tabulatr/tabulatr/finder/find_for_table_spec.rb +0 -187
  88. /data/lib/{generators → tabulatr/generators}/tabulatr/templates/tabulatr.rb +0 -0
@@ -1,145 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- class Tabulatr
25
-
26
- # the method used to actually define the filters of the columns,
27
- # taking the name of the attribute and a hash of options.
28
- #
29
- # The following options are evaluated here:
30
- # <tt>:filter_html</tt>:: a hash with html-attributes added to the <ts>s created
31
- # <tt>:filter</tt>:: may take different values:
32
- # <tt>false</tt>:: no filter is output for this column
33
- # a container:: the keys of the hash are used to define a <tt>select</tt>
34
- # where the values are the <tt>value</tt> of the <tt>options</tt>.
35
- # an Array:: the elements of that array are used to define a
36
- # <tt>select</tt>
37
- # a String:: a <tt>select</tt> is created with that String as options
38
- # you can use ActionView#collection_select and the like
39
- def filter_column(name, opts={}, &block)
40
- raise "Not in filter mode!" if @row_mode != :filter
41
- opts = normalize_column_options(name, opts)
42
- of = opts[:filter]
43
- iname = "#{@classname}#{@table_form_options[:filter_postfix]}[#{name}]"
44
- filter_name = "tabulatr_form_#{name}"
45
- build_filter(of, filter_name, name, iname, opts) if filterable?(of, name.to_s)
46
- end
47
-
48
- # the method used to actually define the filters of the columns,
49
- # taking the name of the attribute and a hash of options.
50
- #
51
- # The following options are evaluated here:
52
- # <tt>:filter_html</tt>:: a hash with html-attributes added to the <ts>s created
53
- # <tt>:filter</tt>:: may take different values:
54
- # <tt>false</tt>:: no filter is output for this column
55
- # a Hash:: the keys of the hash are used to define a <tt>select</tt>
56
- # where the values are the <tt>value</tt> of the <tt>options</tt>.
57
- # an Array:: the elements of that array are used to define a
58
- # <tt>select</tt>
59
- # a subclass of <tt>ActiveRecord::Base</tt>:: a <tt>select</tt> is created
60
- # with all instances
61
- def filter_association(relation, name, opts={}, &block)
62
- raise "Not in filter mode!" if @row_mode != :filter
63
- opts = normalize_column_options(name, opts)
64
-
65
- of = opts[:filter]
66
- iname = "#{@classname}#{@table_form_options[:filter_postfix]}[#{@table_form_options[:associations_filter]}][#{relation}.#{name}]"
67
- filter_name = "tabulatr_form_#{relation}_#{name}"
68
- build_filter(of, filter_name, name, iname, opts, relation) if filterable?(of, name.to_s, relation)
69
- end
70
-
71
- def filter_checkbox(opts={}, &block)
72
- raise "Whatever that's for!" if block_given?
73
- make_tag(:td, opts[:filter_html]) {}
74
- end
75
-
76
- def filter_action(opts={}, &block)
77
- raise "Not in filter mode!" if @row_mode != :filter
78
- opts = normalize_column_options(:action_column, opts)
79
- make_tag(:td, opts[:filter_html]) do
80
- concat(t(opts[:filter])) unless [true, false, nil].member?(opts[:filter])
81
- end # </td>
82
- end
83
-
84
- private
85
-
86
- def filter_tag(of, name, iname, attr_name, opts)
87
- if !of
88
- ""
89
- elsif of.is_a?(Hash) or of.is_a?(Array) or of.is_a?(String)
90
- make_tag(:select, :style => "width:#{opts[:filter_width]}",
91
- :id => name, name: iname) do
92
- if of.class.is_a?(String)
93
- concat(of)
94
- else
95
- concat("<option></option>")
96
- t = options_for_select(of)
97
- concat(t.sub("value=\"\"", "value=\"\" selected=\"selected\""))
98
- end
99
- end # </select>
100
- elsif opts[:filter] == :range
101
- filter_text_tag(opts[:filter_width], "#{name}_from", iname, attr_name, 'from')
102
- concat(t(opts[:range_filter_symbol]))
103
- filter_text_tag(opts[:filter_width], "#{name}_to", iname, attr_name, 'to')
104
- elsif opts[:filter] == :checkbox
105
- checkbox_value = opts[:checkbox_value]
106
- checkbox_label = opts[:checkbox_label]
107
- concat(check_box_tag(iname, checkbox_value, false, {}))
108
- concat(checkbox_label)
109
- elsif opts[:filter] == :exact
110
- filter_text_tag(opts[:filter_width], name, iname, attr_name, 'normal')
111
- else
112
- filter_text_tag(opts[:filter_width], name, iname, attr_name, 'like')
113
- end # if
114
- end
115
-
116
- def filter_text_tag width, name, iname, attr_name, type=nil
117
- name_attribute = iname
118
- name_attribute += "[#{type}]" if type && type != 'normal'
119
- make_tag(:input, :type => :text, :id => name,
120
- :style => "width:#{width}",
121
- :value => '',
122
- :'data-type' => type,
123
- :'data-tabulatr-attribute' => attr_name,
124
- :class => 'tabulatr_filter',
125
- :name => name_attribute)
126
- end
127
-
128
- def build_filter(of, filter_name, name, iname, opts, relation=nil)
129
- if of
130
- make_tag(:div, class: 'control-group') do
131
- make_tag(:label, class: 'control-label', for: filter_name) do
132
- concat(t(opts[:header] || readable_name_for(name, relation)), :escape_html)
133
- end
134
- make_tag(:div, class: 'controls') do
135
- filter_tag(of, filter_name, iname, name, opts)
136
- end
137
- end
138
- end
139
- end
140
-
141
- def filterable?(of, name, relation=nil)
142
- of && (!(relation && name.to_sym == :count))
143
- end
144
-
145
- end
@@ -1,6 +0,0 @@
1
- class Tabulatr
2
- def render_filter_icon
3
- make_tag(:a, class: 'btn btn-info', href: "#tabulatr_filter_dialog_#{@klass.to_s.downcase}",
4
- :'data-toggle' => 'modal'){ concat('<i class="icon-filter"></i>Filter') }
5
- end
6
- end
@@ -1,187 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- # These are extensions for use from ActionController instances
25
- # In a seperate class call only for clearity
26
-
27
- require 'activerecord_outer_joins'
28
-
29
- module Tabulatr::Finder
30
-
31
- # -------------------------------------------------------------------
32
- # Called if SomeActveRecordSubclass::find_for_table(params) is called
33
- #
34
- def self.find_for_table(klaz, params, options={}, &block)
35
- adapter = if klaz.respond_to?(:descends_from_active_record?) then ::Tabulatr::Adapter::ActiveRecordAdapter.new(klaz)
36
- else raise("Don't know how to deal with class '#{klaz}'")
37
- end
38
-
39
- Tabulatr::Security.validate!("#{params[:arguments]}-#{params[:salt]}-#{params[:hash]}")
40
-
41
- form_options = Tabulatr.table_form_options
42
- opts = Tabulatr.finder_options.merge(options)
43
- params ||= {} # just to be sure
44
- cname = adapter.class_to_param
45
- sort_name = "#{cname}#{form_options[:sort_postfix]}"
46
- filter_name = "#{cname}#{form_options[:filter_postfix]}"
47
- batch_name = "#{cname}#{form_options[:batch_postfix]}"
48
- check_name = "tabulatr_checked"
49
- append = params[:append].present? ? params[:append] : false
50
-
51
-
52
- append = string_to_boolean append
53
- # before we do anything else, we find whether there's something to do for batch actions
54
- checked_param = ActiveSupport::HashWithIndifferentAccess.new({:checked_ids => '', :current_page => []}).
55
- merge(params[check_name] || {})
56
-
57
- id = adapter.primary_key
58
-
59
- serializer = options[:serializer].presence
60
-
61
- # checkboxes
62
- checked_ids = checked_param[:checked_ids]
63
- selected_ids = checked_ids.split(',')
64
-
65
- execute_batch_actions(params[batch_name], selected_ids, &block)
66
-
67
- # at this point, we've retrieved the filter settings, the sorting setting, the pagination settings and
68
- # the selected_ids.
69
- filter_param = (params[filter_name] || {})
70
- sortparam = params[sort_name]
71
-
72
- includes = []
73
- maps = klaz.tabulatr_name_mappings.merge(opts[:name_mapping] || {})
74
-
75
- build_conditions(filter_param, form_options, includes, adapter, maps)
76
- order = build_order(params[:sort_by], params[:orientation], params[:default_order], maps, adapter, klaz)
77
-
78
- c = adapter.includes(includes).references(includes).count
79
- # Group statments return a hash
80
- c = c.count unless c.class == Fixnum
81
- pagesize = params[:pagesize]
82
- pagination_data = build_offset(params[:page], pagesize, c, opts)
83
-
84
- total = adapter.preconditions_scope(opts).count
85
- # here too
86
- total = total.count unless total.class == Fixnum
87
-
88
- # Now, actually find the stuff
89
- opts[:name_mapping] ||= {}
90
- find_on = (klaz.tabulatr_select_attributes(opts[:name_mapping]).try do |s| adapter.select(s) end) || adapter
91
- found = find_on.outer_joins(includes)
92
- .limit(pagination_data[:pagesize]).offset(pagination_data[:offset])
93
- .order(order).to_a
94
-
95
- found.define_singleton_method(:__pagination) do
96
- { :page => pagination_data[:page],
97
- :pagesize => pagination_data[:pagesize],
98
- :count => c,
99
- :pages => pagination_data[:pages],
100
- :pagesizes => {},
101
- :total => total,
102
- :append => append,
103
- :table_id => params[:table_id] }
104
- end
105
-
106
- found.define_singleton_method(:to_tabulatr_json) do |klass=nil|
107
- Tabulatr::JsonBuilder.build found, klass, params[:arguments], id
108
- end
109
-
110
- found
111
- end
112
-
113
- private
114
-
115
- def self.execute_batch_actions batch_param, selected_ids, &block
116
- if batch_param.present? && block_given?
117
- batch_param = batch_param.keys.first.to_sym if batch_param.is_a?(Hash)
118
- yield(Invoker.new(batch_param, selected_ids))
119
- end
120
- end
121
-
122
- def self.build_conditions filter_param, form_options, includes, adapter, maps
123
- filter_param.each do |filter|
124
- name, value = filter
125
- next unless value.present?
126
- if (name != form_options[:associations_filter])
127
- table_name = adapter.table_name
128
- nn = extract_column_name(table_name, name, maps)
129
- adapter.add_conditions_from(nn, value)
130
- else
131
- value.each do |assoc_filter|
132
- name,value = assoc_filter
133
- assoc, att = name.split(".").map(&:to_sym)
134
- includes << assoc
135
- table_name = adapter.table_name_for_association(assoc)
136
- nn = extract_column_name(table_name, name, maps, att)
137
- adapter.add_conditions_from(nn, value)
138
- end
139
- end
140
- end
141
- end
142
-
143
- def self.extract_column_name(table_name, n, maps, att=nil)
144
- if maps[n.to_sym]
145
- maps[n.to_sym]
146
- else
147
- if att
148
- t = "#{table_name}.#{att}"
149
- else
150
- t = "#{table_name}.#{n}"
151
- end
152
- raise "SECURITY violation, field name is '#{t}'" unless /^[\d\w]+(\.[\d\w]+)?$/.match t
153
- t
154
- end
155
- end
156
-
157
- def self.build_order sort_by, orientation, default_order, maps, adapter, klaz
158
- if sort_by.present?
159
- s_by = maps[sort_by] ? maps[sort_by] : sort_by
160
- adapter.order_for_query_new s_by, orientation
161
- else
162
- default_order || "#{klaz.table_name}.#{klaz.primary_key} asc"
163
- end
164
- end
165
-
166
- def self.build_offset page, pagesize=10, count, opts
167
- page ||= 1
168
- pagesize, page = pagesize.to_i, page.to_i
169
- pagesize = 10 if pagesize == 0
170
-
171
- pages = (count/pagesize.to_f).ceil
172
-
173
- {offset: ((page-1)*pagesize).to_i, pagesize: pagesize.to_i, pages: pages,
174
- page: page
175
- }
176
- end
177
-
178
- def self.string_to_boolean str
179
- if str == 'true'
180
- str = true
181
- elsif str == 'false'
182
- str = false
183
- end
184
- str
185
- end
186
-
187
- end
@@ -1,64 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- # These are extensions for use from ActionController instances
25
- module Tabulatr::Finder
26
-
27
- require File.join(File.dirname(__FILE__), 'finder', 'find_for_table')
28
-
29
- # compress the list of ids as good as I could imagine ;)
30
- # uses fancy base twisting
31
- def self.compress_id_list(list)
32
- if list.length == 0
33
- ""
34
- else
35
- "GzB" + Base64.encode64(
36
- Zlib::Deflate.deflate(
37
- list.join(Tabulatr.table_form_options[:checked_separator])))
38
- end
39
- end
40
-
41
- # inverse of compress_id_list
42
- def self.uncompress_id_list(str)
43
- if !str.present?
44
- []
45
- elsif str.starts_with?("GzB")
46
- Zlib::Inflate.inflate(Base64.decode64(str[3..-1])).split(
47
- Tabulatr.table_form_options[:checked_separator])
48
- end
49
- end
50
-
51
- class Invoker
52
- def initialize(batch_action, ids)
53
- @batch_action = batch_action.to_sym
54
- @ids = ids
55
- end
56
-
57
- def method_missing(name, *args, &block)
58
- if @batch_action == name
59
- yield(@ids)
60
- end
61
- end
62
- end
63
-
64
- end
@@ -1,146 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- class Tabulatr
25
-
26
-
27
- # the method used to actually define the headers of the columns,
28
- # taking the name of the attribute and a hash of options.
29
- #
30
- # The following options are evaluated here:
31
- # <tt>:th_html</tt>:: a hash with html-attributes added to the <th>s created
32
- # <tt>:header</tt>:: if present, the value will be output in the header cell,
33
- # otherwise, the capitalized name is used
34
- def header_column(name, opts={}, &block)
35
- raise "Not in header mode!" if @row_mode != :header
36
- sortparam = "#{@classname}#{@table_form_options[:sort_postfix]}"
37
- filter_name = "#{@classname}#{@table_form_options[:filter_postfix]}[#{name}]"
38
- bid = "#{@classname}#{@table_form_options[:sort_postfix]}"
39
-
40
- create_header_tag(name, opts, sortparam, filter_name, name,
41
- nil, bid
42
- )
43
- # opts = normalize_column_options(name, opts)
44
- # opts = normalize_header_column_options opts
45
- # opts[:th_html]['data-tabulatr-column-name'] = name
46
- # opts[:th_html]['data-tabulatr-form-name'] = filter_name
47
- # opts[:th_html]['data-tabulatr-sorting-name'] = "#{@klass.table_name}.#{name}"
48
- # make_tag(:th, opts[:th_html]) do
49
- # concat(t(opts[:header] || readable_name_for(name)), :escape_html)
50
- # create_sorting_elements opts, sortparam, name, bid
51
- # end # </th>
52
- end
53
-
54
- # the method used to actually define the headers of the columns,
55
- # taking the name of the attribute and a hash of options.
56
- #
57
- # The following options are evaluated here:
58
- # <tt>:th_html</tt>:: a hash with html-attributes added to the <th>s created
59
- # <tt>:header</tt>:: if present, the value will be output in the header cell,
60
- # otherwise, the capitalized name is used
61
- def header_association(relation, name, opts={}, &block)
62
- raise "Not in header mode!" if @row_mode != :header
63
- create_header_tag(name, opts,
64
- "#{@classname}#{@table_form_options[:sort_postfix]}[#{relation.to_s}.#{name.to_s}]",
65
- "#{@classname}#{@table_form_options[:filter_postfix]}[#{@table_form_options[:associations_filter]}][#{relation.to_s}.#{name.to_s}]",
66
- "#{relation}:#{name}",
67
- relation
68
- )
69
- end
70
-
71
- def header_checkbox(opts={}, &block)
72
- raise "Whatever that's for!" if block_given?
73
- opts = normalize_column_options(:checkbox_column, opts)
74
- opts = normalize_header_column_options opts, :checkbox
75
- make_tag(:th, opts[:th_html]) do
76
- make_tag(:input, type: 'checkbox', :'data-table' => "#{@klass.to_s.downcase}_table",
77
- class: "tabulatr_mark_all"){}
78
- render_batch_actions if @table_options[:batch_actions]
79
- end
80
- end
81
-
82
- def header_action(opts={}, &block)
83
- raise "Please specify a block" unless block_given?
84
- opts = normalize_column_options(:action_column, opts)
85
- opts = normalize_header_column_options opts, :action
86
- dummy = DummyRecord.for(@klass)
87
- cont = yield(dummy)
88
- cont = cont.join(' ') if cont.is_a? Array
89
- opts[:th_html]['data-tabulatr-action'] = cont.gsub('"', "'")
90
- @attributes = (@attributes + dummy.requested_methods).flatten
91
- names = dummy.requested_methods.join(',')
92
-
93
- make_tag(:th, opts[:th_html].merge('data-tabulatr-column-name' => names)) do
94
- concat(t(opts[:header] || ""), :escape_html)
95
- end
96
- end
97
-
98
- private
99
-
100
- def normalize_header_column_options opts, type=nil
101
- opts[:th_html] ||= {}
102
- opts[:th_html]['data-tabulatr-column-type'] = type if type
103
- if opts[:format_methods]
104
- opts[:th_html]['data-tabulatr-methods'] = opts[:format_methods].join(',')
105
- end
106
- opts
107
- end
108
-
109
- def create_sorting_elements opts, sortparam, name, bid=""
110
- if opts[:sortable] and @table_options[:sortable]
111
- if @sorting and @sorting[:by].to_s == name.to_s
112
- pname = "#{sortparam}[_resort][#{name}]"
113
- bid = "#{bid}_#{name}"
114
- sort_dir = @sorting[:direction] == 'asc' ? 'desc' : 'asc'
115
- make_tag(:input, :type => :hidden,
116
- :name => "#{sortparam}[#{name}][#{@sorting[:direction]}]",
117
- :value => "#{@sorting[:direction]}")
118
- else
119
- pname = "#{sortparam}[_resort][#{name}]"
120
- bid = "#{bid}_#{name}"
121
- sort_dir = 'desc'
122
- end
123
- make_image_button(:id => bid, :name => pname, :'data-sort' => sort_dir)
124
- end
125
- end
126
-
127
-
128
- def create_header_tag name, opts, sort_param, filter_name, column_name, relation=nil, bid=nil
129
- opts = normalize_column_options(name, opts)
130
- opts = normalize_header_column_options(opts)
131
- opts[:th_html]['data-tabulatr-column-name'] = column_name
132
- opts[:th_html]['data-tabulatr-form-name'] = filter_name
133
- opts[:th_html]['data-tabulatr-sorting-name'] = sorting_name(name, relation)
134
- make_tag(:th, opts[:th_html]) do
135
- concat(t(opts[:header] || readable_name_for(name, relation)), :escape_html)
136
- create_sorting_elements(opts, sort_param, name, bid) unless relation && name.to_sym == :count
137
- end # </th>
138
- end
139
-
140
- def sorting_name name, relation=nil
141
- return "#{@klass.reflect_on_association(relation).table_name}.#{name}" if relation && @klass.reflect_on_association(relation).klass.column_names.include?(name.to_s)
142
- return "#{@klass.table_name}.#{name}" if @klass.column_names.include?(name.to_s)
143
- name
144
- end
145
-
146
- end
@@ -1,57 +0,0 @@
1
- module Tabulatr::JsonBuilder
2
- def self.build(data, klass, requested_attributes, id)
3
- if klass && ActiveModel.const_defined?(:ArraySerializer)
4
- ActiveModel::ArraySerializer.new(data,
5
- { root: "data", meta: data.__pagination,
6
- each_serializer: klass
7
- }).as_json
8
- else
9
- id_included = false
10
- attrs = build_hash_from requested_attributes, id
11
- result = []
12
- data.each do |f|
13
- tmp = {}
14
- attrs.each do |at|
15
- insert_attribute_in_hash(at, f, tmp)
16
- end
17
- result << tmp
18
- end
19
- { data: result, meta: data.__pagination }
20
- end
21
- end
22
-
23
- private
24
-
25
- def self.build_hash_from requested_attributes, id
26
- attrs = []
27
- id_included = false
28
- requested_attributes.split(',').each do |par|
29
- if par.include? ':'
30
- relation, action = par.split(':')
31
- attrs << {action: action, relation: relation}
32
- else
33
- id_included = true if par == id
34
- attrs << {action: par}
35
- end
36
- end
37
- attrs << {action: id} unless id_included
38
- attrs
39
- end
40
-
41
- def self.insert_attribute_in_hash at, f, r={}
42
- if at.has_key? :relation
43
- if f.class.reflect_on_association(at[:relation].to_sym).collection?
44
- if at[:action].to_sym == :count
45
- r["#{at[:relation]}:#{at[:action]}"] = f.try(at[:relation]).count
46
- else
47
- r["#{at[:relation]}:#{at[:action]}"] = f.try(at[:relation]).map(&at[:action].to_sym).join(', ')
48
- end
49
- else
50
- r["#{at[:relation]}:#{at[:action]}"] = f.try(at[:relation]).try(at[:action])
51
- end
52
- else
53
- r[at[:action]] = f.send at[:action]
54
- end
55
- r
56
- end
57
- end
@@ -1,76 +0,0 @@
1
- #--
2
- # Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- class Tabulatr
25
-
26
- #render the paginator controls, inputs etc.
27
- def render_paginator
28
- # get the current pagination state
29
- if (@table_options[:paginate].is_a?(Fixnum)) && @klass.count > @table_options[:paginate] ||
30
- @table_options[:paginate] === true
31
- send(Tabulatr.bootstrap_paginator)
32
- end
33
- make_tag(:div, :class => 'btn-group tabulatr-per-page', :'data-table' => "#{@klass.to_s.downcase}_table") do
34
- make_tag(:button, :class => 'btn') do
35
- concat(I18n.t('tabulatr.rows_per_page'))
36
- end
37
- make_tag(:button, :class => 'btn dropdown-toggle', :'data-toggle' => 'dropdown') do
38
- make_tag(:span, :class => 'caret'){}
39
- end
40
- make_tag(:ul, :class => 'dropdown-menu') do
41
- [10, 25, 50, 100].push(@table_options[:default_pagesize]).uniq.sort.each do |n|
42
- create_pagination_select(n, n == @table_options[:default_pagesize])
43
- end
44
- end
45
- end
46
- end
47
-
48
- def create_pagination_select n, default=false
49
- make_tag(:li) do
50
- params = { :href => "javascript: void(0);",
51
- :'data-items-per-page' => n }
52
- params[:class] = 'active' if default
53
- make_tag(:a, params) do
54
- concat(n)
55
- end
56
- end
57
- end
58
-
59
- private
60
-
61
- # bootstrap 3
62
- def create_ul_paginator
63
- make_tag(:ul, :class => @table_options[:paginator_div_class],
64
- :'data-table' => "#{@klass.to_s.downcase}_table") do
65
- end
66
- end
67
-
68
- # bootstrap 2
69
- def create_div_paginator
70
- make_tag(:div, :class => @table_options[:paginator_div_class],
71
- :'data-table' => "#{@klass.to_s.downcase}_table") do
72
- make_tag(:ul){}
73
- end
74
- end
75
-
76
- end