data_grid 0.0.1 → 0.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.
Files changed (114) hide show
  1. data/.rspec +3 -0
  2. data/CHANGELOG +5 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/Rakefile +1 -0
  6. data/app/assets/images/data_grid/calendar_view_month.png +0 -0
  7. data/app/assets/images/data_grid/csv.gif +0 -0
  8. data/app/assets/images/data_grid/delete.png +0 -0
  9. data/app/assets/images/data_grid/edit.png +0 -0
  10. data/app/assets/images/data_grid/no.png +0 -0
  11. data/app/assets/images/data_grid/sort_down.gif +0 -0
  12. data/app/assets/images/data_grid/sort_up.gif +0 -0
  13. data/app/assets/images/data_grid/yes.png +0 -0
  14. data/app/assets/javascripts/data_grid/data_grid.js +24 -0
  15. data/app/assets/javascripts/data_grid/grid_calendar/calendar-setup.js +200 -0
  16. data/app/assets/javascripts/data_grid/grid_calendar/calendar-setup_stripped.js +21 -0
  17. data/app/assets/javascripts/data_grid/grid_calendar/calendar.js +1819 -0
  18. data/app/assets/javascripts/data_grid/grid_calendar/calendar_original.js +1845 -0
  19. data/app/assets/javascripts/data_grid/grid_calendar/calendar_patched.js +1819 -0
  20. data/app/assets/javascripts/data_grid/grid_calendar/calendar_stripped.js +14 -0
  21. data/app/assets/javascripts/data_grid/grid_calendar/img.gif +0 -0
  22. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-af.js +39 -0
  23. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-al.js +101 -0
  24. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-bg.js +124 -0
  25. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-big5-utf8.js +123 -0
  26. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-big5.js +123 -0
  27. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-br.js +108 -0
  28. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ca.js +123 -0
  29. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-cs-utf8.js +65 -0
  30. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-cs-win.js +65 -0
  31. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-da.js +123 -0
  32. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-de.js +124 -0
  33. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-du.js +45 -0
  34. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-el.js +89 -0
  35. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-en.js +127 -0
  36. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-es.js +129 -0
  37. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-fi.js +98 -0
  38. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-fr.js +125 -0
  39. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-he-utf8.js +123 -0
  40. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-hr-utf8.js +49 -0
  41. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-hr.js +0 -0
  42. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-hu.js +124 -0
  43. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-it.js +124 -0
  44. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-jp.js +45 -0
  45. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ko-utf8.js +120 -0
  46. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ko.js +120 -0
  47. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-lt-utf8.js +114 -0
  48. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-lt.js +114 -0
  49. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-lv.js +123 -0
  50. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-nl.js +73 -0
  51. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-no.js +114 -0
  52. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-pl-utf8.js +93 -0
  53. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-pl.js +56 -0
  54. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-pt.js +123 -0
  55. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ro.js +66 -0
  56. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ru.js +123 -0
  57. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-ru_win_.js +123 -0
  58. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-si.js +94 -0
  59. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-sk.js +99 -0
  60. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-sp.js +110 -0
  61. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-sv.js +93 -0
  62. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-tr.js +58 -0
  63. data/app/assets/javascripts/data_grid/grid_calendar/lang/calendar-zh.js +119 -0
  64. data/app/assets/javascripts/data_grid/grid_calendar/lang/cn_utf8.js +123 -0
  65. data/app/assets/javascripts/data_grid/grid_calendar/menuarrow.gif +0 -0
  66. data/app/assets/javascripts/data_grid/grid_calendar/menuarrow2.gif +0 -0
  67. data/app/assets/stylesheets/data_grid/data_grid.css +90 -0
  68. data/app/assets/stylesheets/data_grid/data_grid_3_0.css +90 -0
  69. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-blue.css +233 -0
  70. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-blue2.css +237 -0
  71. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-brown.css +226 -0
  72. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-green.css +230 -0
  73. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-system.css +252 -0
  74. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-tas.css +240 -0
  75. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-1.css +272 -0
  76. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-2.css +272 -0
  77. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-cold-1.css +266 -0
  78. data/app/assets/stylesheets/data_grid/grid_calendar/calendar-win2k-cold-2.css +272 -0
  79. data/app/assets/stylesheets/data_grid/grid_calendar/img.gif +0 -0
  80. data/app/assets/stylesheets/data_grid/grid_calendar/menuarrow.gif +0 -0
  81. data/app/assets/stylesheets/data_grid/grid_calendar/menuarrow2.gif +0 -0
  82. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/active-bg.gif +0 -0
  83. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/dark-bg.gif +0 -0
  84. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/hover-bg.gif +0 -0
  85. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/menuarrow.gif +0 -0
  86. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/normal-bg.gif +0 -0
  87. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/rowhover-bg.gif +0 -0
  88. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/status-bg.gif +0 -0
  89. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/theme.css +236 -0
  90. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/title-bg.gif +0 -0
  91. data/app/assets/stylesheets/data_grid/grid_calendar/skins/aqua/today-bg.gif +0 -0
  92. data/app/views/data_grid/_data_grid.html.erb +101 -0
  93. data/config/locales/en.yml +10 -0
  94. data/data_grid.gemspec +27 -0
  95. data/lib/data_grid/column.rb +38 -0
  96. data/lib/data_grid/controller.rb +30 -0
  97. data/lib/data_grid/cookies_state_saver.rb +42 -0
  98. data/lib/data_grid/csv_exporter.rb +79 -0
  99. data/lib/data_grid/data_grid_logic.rb +175 -0
  100. data/lib/data_grid/data_source_array.rb +267 -0
  101. data/lib/data_grid/data_source_orm.rb +207 -0
  102. data/lib/data_grid/engine.rb +19 -0
  103. data/lib/data_grid/summaries.rb +34 -0
  104. data/lib/data_grid/version.rb +3 -0
  105. data/lib/data_grid/view_helpers.rb +271 -0
  106. data/lib/data_grid.rb +43 -0
  107. data/lib/generators/data_grid/copy_view_generator.rb +16 -0
  108. data/lib/generators/data_grid/install_generator.rb +29 -0
  109. data/lib/generators/templates/data_grid.rb +29 -0
  110. data/lib/generators/templates/stylesheets/data_grid/data_grid_3_0.css +90 -0
  111. data/spec/orm_spec.rb +57 -0
  112. data/spec/spec_helper.rb +15 -0
  113. data/spec/support/active_record.rb +17 -0
  114. metadata +118 -5
@@ -0,0 +1,175 @@
1
+ module DataGrid
2
+ class DataGridLogic
3
+
4
+ attr_accessor :per_page, :page, :name, :columns, :in_data, :out_data, :data_class, :params, :sort, :sort_direction, :view_context, :pages, :total, :export_enabled, :summaries, :row_styles, :state_saver, :show_footer, :hidden_row, :out_hidden_rows, :initial_sort, :global_summaries, :count_statement, :extra_orm_options, :export_filename
5
+
6
+
7
+ # Initialize
8
+ def initialize(attrs = {})
9
+ # Internal copy od request params
10
+ self.params = attrs[:params].except(:action).except(:controller).except(:utf8)
11
+
12
+ # Display rows per page
13
+ self.per_page = (attrs[:per_page] || DataGrid.per_page).to_i
14
+
15
+ # Current page
16
+ self.page = (attrs[:page] || 1).to_i
17
+ self.page = 1 if self.page <= 0
18
+ self.page = 1 if self.page >= 10000000
19
+
20
+ # DataGrid name. Has to be set if two or more grids on page.
21
+ self.name = attrs[:name] || ''
22
+
23
+ # Sort by this field
24
+ self.sort = attrs[:sort]
25
+
26
+ # Sort direction - (asc, desc)
27
+ self.sort_direction = attrs[:sort] || DataGrid.sort_direction
28
+
29
+ # Internal array of columns
30
+ self.columns = attrs[:columns] || []
31
+
32
+ # Internal representation of prepared data to display
33
+ self.out_data = []
34
+
35
+ # Name of state saver method - (cookies)
36
+ self.state_saver = attrs[:state_saver]
37
+
38
+ # Show grid footer?
39
+ self.show_footer = attrs[:show_footer] || DataGrid.show_footer
40
+
41
+ # Internal representation of hidden rows - row below each row
42
+ self.hidden_row = attrs[:hidden_row]
43
+
44
+ # Internal representation of prepared hidden rows
45
+ self.out_hidden_rows = []
46
+
47
+ # Initial data grid sorting (ie. 'age ASC')
48
+ self.initial_sort = attrs[:initial_sort]
49
+
50
+ # SQL which counts rows
51
+ self.count_statement = attrs[:count_statement] || nil
52
+
53
+ # Extra where statement
54
+ self.extra_orm_options = attrs[:extra_orm_options] || nil
55
+
56
+ # Name of exported filename
57
+ self.export_filename = attrs[:export_filename] || DataGrid.export_filename
58
+
59
+ # Name of export method - (csv)
60
+ self.export_enabled = attrs[:export_enabled]
61
+ end
62
+
63
+ # Add new column
64
+ def add_column(column_field, column_attrs = {})
65
+ self.columns << Column.new(column_field, column_attrs)
66
+ end
67
+
68
+ # Assign data
69
+ def data(_data)
70
+ self.in_data = _data
71
+ self.data_class = _data
72
+ self.data_class = _data.class
73
+ self.data_class = _data if _data.class != Array
74
+ end
75
+
76
+ # Sorting comes from URL?
77
+ def sorting?
78
+ !self.sort.nil?
79
+ end
80
+
81
+ # Any column has filters?
82
+ def filters?
83
+ !self.columns.select{|c| !c.filter.nil?}.empty?
84
+ end
85
+
86
+ # Any column has summary?
87
+ def summary?
88
+ !self.columns.select{|c| !c.summary.nil?}.empty?
89
+ end
90
+
91
+ # Any column has global summary?
92
+ def global_summary?
93
+ !self.columns.select{|c| !c.global_summary.nil?}.empty?
94
+ end
95
+
96
+ # Display footer?
97
+ def footer?
98
+ self.show_footer
99
+ end
100
+
101
+ # Get params from request
102
+ def get_params_from_request
103
+ self.per_page = (params["per_page_#{self.name}"] || self.per_page).to_i
104
+ self.page = (params["page_#{self.name}"] || self.page).to_i
105
+ self.sort = params["sort_#{self.name}"] ? params["sort_#{self.name}"].split('_').pop.to_i : self.sort
106
+ self.sort_direction = params["sort_direction_#{self.name}"] || self.sort_direction
107
+
108
+ self.columns.each_with_index do |col, col_index|
109
+ col.filter_value = params["filter_#{self.name}_#{col_index}"]
110
+ if params["filter_#{self.name}_#{col_index}_from"] or params["filter_#{self.name}_#{col_index}_to"]
111
+ col.filter_value = params["filter_#{self.name}_#{col_index}_from"].to_s + DataGrid.range_separator +
112
+ params["filter_#{self.name}_#{col_index}_to"].to_s
113
+ end
114
+ end
115
+ end
116
+
117
+ # Used in view to show entries from
118
+ def entries_from
119
+ ef = (self.page-1)*self.per_page
120
+ ef.zero? ? 1 : ef
121
+ end
122
+
123
+ # Used in view to show entries to
124
+ def entries_to
125
+ if (self.page)*self.per_page > total
126
+ total
127
+ else
128
+ (self.page)*self.per_page
129
+ end
130
+ end
131
+
132
+ # Assign data
133
+ def data(_data)
134
+ self.in_data = _data
135
+ self.data_class = _data
136
+ self.data_class = _data.class
137
+ self.data_class = _data if _data.class != Array
138
+ end
139
+
140
+ alias :data= :data
141
+
142
+
143
+ # Prepare data, do sorting, filtering, paging
144
+ def prepare_data
145
+ data_source = nil
146
+ if self.data_class == Array
147
+ require 'data_grid/data_source_array'
148
+ data_source = DataGrid::DataSourceArray.new
149
+ else
150
+ require 'data_grid/data_source_orm'
151
+ data_source = DataGrid::DataSourceORM.new
152
+ end
153
+
154
+ data_source.data_grid = self
155
+ data_source.prepare_data
156
+ end
157
+
158
+
159
+ # Row styler is a column, which is hidden and describes style of the row
160
+ def row_styler
161
+ styler_column = self.columns.select{|col| col.title == :row_styler}
162
+
163
+ if styler_column and !styler_column.empty?
164
+ styler_column_index = self.columns.index(styler_column.first)
165
+
166
+ self.row_styles = []
167
+ self.out_data.each do |row|
168
+ self.row_styles << row[styler_column_index]
169
+ end
170
+
171
+ self.columns.delete_at(styler_column_index)
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,267 @@
1
+ # Source od grid data comes from Array
2
+
3
+ module DataGrid
4
+ class DataSourceArray
5
+
6
+ attr_accessor :data_grid
7
+
8
+ # Main function which prepares data
9
+ def prepare_data
10
+ initial_data_eval
11
+ initial_sorting if self.data_grid.sorting?
12
+ filter
13
+ global_summary_array
14
+ pagination
15
+ summary_array
16
+ self.data_grid.row_styler
17
+ prepare_data_for_filters
18
+ end
19
+
20
+
21
+ private
22
+
23
+ def direction_as_int
24
+ if self.data_grid.sort_direction == 'ASC'
25
+ return 1
26
+ else
27
+ return -1
28
+ end
29
+ end
30
+
31
+ # Eval lambdas
32
+ def initial_data_eval
33
+ self.data_grid.in_data.each_with_index do |row, row_index|
34
+ entry = []
35
+
36
+ self.data_grid.columns.each_with_index do |col, index|
37
+ # Eval if sorting or filtering by or summary column
38
+ if (self.data_grid.sort == index) or (col.filter and !col.filter_value.blank?) or col.global_summary or col.summary
39
+ if col.sort_by.class == Symbol
40
+ if col.sort_by != col.field
41
+ if col.field.class == Symbol
42
+ to_entry = [row.send(col.field), row.send(col.sort_by)]
43
+ else
44
+ to_entry = [col.field.call(row, self.data_grid.view_context), row.send(col.sort_by)]
45
+ end
46
+ else
47
+ to_entry = row.send(col.sort_by)
48
+ end
49
+ else
50
+ # Call lambda
51
+ to_entry = col.field.call(row, self.data_grid.view_context)
52
+ end
53
+ else
54
+ # Other column are not evaluated, for now has only row index
55
+ to_entry = row_index
56
+ end
57
+
58
+ to_entry = 0 if to_entry.nil?
59
+ entry << to_entry
60
+ end
61
+
62
+ self.data_grid.out_data << entry
63
+ end
64
+ end
65
+
66
+ # Initial sorting
67
+ def initial_sorting
68
+ self.data_grid.out_data.sort! do |a, b|
69
+ a_v = a[self.data_grid.sort]
70
+ b_v = b[self.data_grid.sort]
71
+
72
+ a_v = a_v[1] if a_v.class == Array
73
+ b_v = b_v[1] if b_v.class == Array
74
+
75
+ a_v = a_v.upcase if a_v.class == String
76
+ b_v = b_v.upcase if b_v.class == String
77
+ if (a_v > b_v)
78
+ direction_as_int
79
+ else
80
+ if a_v == b_v
81
+ 0
82
+ else
83
+ direction_as_int * -1
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ # Filter
90
+ def filter
91
+ if self.data_grid.filters?
92
+ date_format = I18n.t(:"date.formats.default", {:locale => I18n.locale })
93
+ filtered_data = []
94
+ self.data_grid.out_data.each do |row|
95
+ add_row = true
96
+ self.data_grid.columns.each_with_index do |col, col_index|
97
+ if col.filter and !col.filter_value.blank?
98
+ case col.filter
99
+ when :auto
100
+ add_row = false if row[col_index] != col.filter_value
101
+ when :text
102
+ add_row = false if row[col_index] !~ Regexp.new(col.filter_value, true) and row[col_index].first !~ Regexp.new(col.filter_value, true)
103
+ when :number
104
+ add_row = false if row[col_index].to_f != col.filter_value.to_f
105
+ when :range
106
+ range = col.filter_value.split(DataGrid.range_separator)
107
+
108
+ if !range[0].blank? and !range[1].blank?
109
+ begin
110
+ range[0] < 2
111
+ rescue
112
+ range[0] = range[0].to_f
113
+ range[1] = range[1].to_f
114
+ end
115
+ add_row = false if row[col_index] < range[0] or row[col_index] > range[1]
116
+ elsif range[0].blank? and !range[1].blank?
117
+ begin
118
+ range[1] < 2
119
+ rescue
120
+ range[1] = range[1].to_f
121
+ end
122
+ add_row = false if row[col_index] > range[1]
123
+ elsif range[1].blank? and !range[0].blank?
124
+ begin
125
+ range[0] < 2
126
+ rescue
127
+ range[0] = range[0].to_f
128
+ end
129
+ add_row = false if row[col_index] < range[0]
130
+ end
131
+
132
+ when :date
133
+ range = col.filter_value.split(DataGrid.range_separator)
134
+
135
+ if !range[0].blank? and !range[1].blank?
136
+ begin
137
+ range[0] < 2
138
+ rescue
139
+ range[0] = DateTime.strptime(range[0], date_format)
140
+ range[1] = DateTime.strptime(range[1], date_format)
141
+ end
142
+ add_row = false if row[col_index].class == Fixnum or row[col_index] < range[0] or row[col_index] > range[1]
143
+ elsif range[0].blank? and !range[1].blank?
144
+ begin
145
+ range[1] < 2
146
+ rescue
147
+ range[1] = DateTime.strptime(range[1], date_format)
148
+ end
149
+ add_row = false if row[col_index].class == Fixnum or row[col_index] > range[1]
150
+ elsif range[1].blank? and !range[0].blank?
151
+ begin
152
+ range[0] < 2
153
+ rescue
154
+ range[0] = DateTime.strptime(range[0], date_format)
155
+ end
156
+ add_row = false if row[col_index].class == Fixnum or row[col_index] < range[0]
157
+ end
158
+
159
+ end
160
+ end
161
+ end
162
+ filtered_data << row if add_row
163
+ end
164
+
165
+ self.data_grid.out_data = filtered_data
166
+ end
167
+ end
168
+
169
+
170
+ # Pagination
171
+ def pagination
172
+ self.data_grid.total = self.data_grid.out_data.size
173
+ self.data_grid.pages = self.data_grid.out_data.size/self.data_grid.per_page
174
+ self.data_grid.pages = (self.data_grid.pages != self.data_grid.pages.ceil) ? self.data_grid.pages.ceil + 1 : self.data_grid.pages.ceil
175
+
176
+ page = self.data_grid.page
177
+ per_page = self.data_grid.per_page
178
+
179
+ offset = (page - 1) * per_page
180
+ if !paged_out_data = self.data_grid.out_data[offset..(offset + per_page - 1)]
181
+ paged_out_data = self.data_grid.out_data[0..(per_page - 1)]
182
+ end
183
+
184
+ self.data_grid.out_data = []
185
+ paged_out_data.each_with_index do |row, row_index|
186
+ entry = []
187
+
188
+ self.data_grid.columns.each_with_index { |col, index|
189
+ # If colum is sorted/filtered/summary
190
+ if (self.data_grid.sort != index) and (!col.filter or col.filter_value.blank?) and !col.summary and !col.global_summary
191
+ field = row[index]
192
+ if col.field.class == Symbol
193
+ if col.field == :auto
194
+ entry << row_index + 1 + (page-1)*per_page
195
+ else
196
+ entry << self.data_grid.in_data[field].send(col.field)
197
+ end
198
+ else
199
+ entry << col.field.call(self.data_grid.in_data[field], self.data_grid.view_context)
200
+ end
201
+ else
202
+ entry << row[index]
203
+ end
204
+ }
205
+
206
+ self.data_grid.out_data << entry
207
+ end
208
+ end
209
+
210
+ # Prepare data for filters
211
+ def prepare_data_for_filters
212
+ self.data_grid.columns.each do |col|
213
+ next if col.filter.nil? # if no filter
214
+
215
+ # Prepare auto filters
216
+ if col.filter == :auto
217
+ self.data_grid.in_data.each do |d|
218
+ if col.sort_by.class == Symbol
219
+ col.filter_data << d.send(col.sort_by)
220
+ else
221
+ # Call lambda
222
+ col.filter_data << col.field.call(d, self.data_grid)
223
+ end
224
+ end
225
+
226
+ col.filter_data.uniq!
227
+ col.filter_data.sort!
228
+ end
229
+ end
230
+ end
231
+
232
+ # Summary
233
+ def summary_array
234
+ if self.data_grid.summary?
235
+ self.data_grid.summaries = []
236
+ self.data_grid.columns.each_with_index do |col, col_index|
237
+ if col.summary
238
+ column_data = []
239
+ self.data_grid.out_data.each do |row|
240
+ column_data << row[col_index]
241
+ end
242
+
243
+ self.data_grid.summaries[col_index] = DataGrid::Summaries.send(col.summary, column_data)
244
+ end
245
+ end
246
+ end
247
+ end
248
+
249
+ # Global Summary
250
+ def global_summary_array
251
+ if self.data_grid.summary?
252
+ self.data_grid.global_summaries = []
253
+ self.data_grid.columns.each_with_index do |col, col_index|
254
+ if col.global_summary
255
+ column_data = []
256
+ self.data_grid.out_data.each do |row|
257
+ column_data << row[col_index]
258
+ end
259
+
260
+ self.data_grid.global_summaries[col_index] = DataGrid::Summaries.send(col.global_summary, column_data)
261
+ end
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end
267
+
@@ -0,0 +1,207 @@
1
+ # Source od grid data comes from ORM
2
+
3
+ module DataGrid
4
+ class DataSourceORM
5
+
6
+ attr_accessor :data_grid
7
+
8
+ def prepare_data
9
+ global_summary_orm
10
+ get_data_from_orm
11
+ summary_orm
12
+ self.data_grid.row_styler
13
+ prepare_orm_data_for_filters
14
+ end
15
+
16
+
17
+ private
18
+
19
+ def direction_as_int
20
+ if self.sort_direction == 'ASC'
21
+ return 1
22
+ else
23
+ return -1
24
+ end
25
+ end
26
+
27
+ # Filter data using ORM
28
+ def prepare_orm_filters
29
+ filters = [[]]
30
+ date_format = I18n.t(:"date.formats.default", {:locale => I18n.locale })
31
+ self.data_grid.columns.each_with_index do |col, col_index|
32
+ if col.filter and !col.filter_value.blank?
33
+ case col.filter
34
+ when :boolean
35
+ filters[0] << "#{col.filter_by} = ?"
36
+ filters << (col.filter_value == '1') ? true : false
37
+ when :auto
38
+ filters[0] << "#{col.filter_by} = ?"
39
+ filters << col.filter_value
40
+ when :text
41
+ filters[0] << "#{col.filter_by} #{ActiveRecord::Base.connection.adapter_name.downcase.to_sym == :postgresql ? 'ILIKE' : 'LIKE'} ?"
42
+ filters << "%#{col.filter_value}%"
43
+ when :number
44
+ filters[0] << "#{col.filter_by} = ?"
45
+ filters << col.filter_value.to_i
46
+ when :range
47
+ range = col.filter_value.split(DataGrid.range_separator)
48
+
49
+ if !range[0].blank? and !range[1].blank?
50
+ begin
51
+ range[0] < 2
52
+ rescue
53
+ range[0] = range[0].to_f
54
+ range[1] = range[1].to_f
55
+ end
56
+ filters[0] << "#{col.filter_by} >= ? AND #{col.filter_by} <= ?"
57
+ filters << range[0]
58
+ filters << range[1]
59
+ elsif range[0].blank? and !range[1].blank?
60
+ begin
61
+ range[1] < 2
62
+ rescue
63
+ range[1] = range[1].to_f
64
+ end
65
+ filters[0] << "#{col.filter_by} <= ?"
66
+ filters << range[1]
67
+ elsif range[1].blank? and !range[0].blank?
68
+ begin
69
+ range[0] < 2
70
+ rescue
71
+ range[0] = range[0].to_f
72
+ end
73
+ filters[0] << "#{col.filter_by} >= ?"
74
+ filters << range[0]
75
+ end
76
+
77
+ when :date
78
+ range = col.filter_value.split(DataGrid.range_separator)
79
+
80
+ if !range[0].blank? and !range[1].blank?
81
+ begin
82
+ range[0] < 2
83
+ rescue
84
+ range[0] = DateTime.strptime(range[0], date_format)
85
+ range[1] = DateTime.strptime(range[1], date_format)
86
+ end
87
+ filters[0] << "#{col.filter_by} >= ? AND #{col.filter_by} <= ?"
88
+ filters << range[0]
89
+ filters << range[1]
90
+ elsif range[0].blank? and !range[1].blank?
91
+ begin
92
+ range[1] < 2
93
+ rescue
94
+ range[1] = DateTime.strptime(range[1], date_format)
95
+ end
96
+ filters[0] << "#{col.filter_by} <= ?"
97
+ filters << range[1]
98
+ elsif range[1].blank? and !range[0].blank?
99
+ begin
100
+ range[0] < 2
101
+ rescue
102
+ range[0] = DateTime.strptime(range[0], date_format)
103
+ end
104
+ filters[0] << "#{col.filter_by} >= ?"
105
+ filters << range[0]
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ filters[0] = filters[0].join(' AND ')
112
+ filters
113
+ end
114
+
115
+ # Get data
116
+ def get_data_from_orm
117
+ self.data_grid.out_data = []
118
+
119
+ # prepare filters as ActiveRecord conditions
120
+ filters = prepare_orm_filters
121
+ self.data_grid.total = self.data_grid.in_data.where(filters).where(self.data_grid.extra_orm_options).count(self.data_grid.count_statement)
122
+ self.data_grid.page = 1 if ((self.data_grid.per_page * (self.data_grid.page - 1)) > self.data_grid.total)
123
+ offset = (self.data_grid.page - 1) * self.data_grid.per_page
124
+
125
+
126
+ # get data sorted
127
+ if self.data_grid.sorting?
128
+ self.data_grid.in_data = self.data_grid.in_data.limit(self.data_grid.per_page.to_i).offset(offset.to_i).order("#{self.data_grid.columns[self.data_grid.sort].sort_field} #{self.data_grid.sort_direction}" + (self.data_grid.initial_sort.blank? ? '' : ", #{self.data_grid.initial_sort}")).where(filters).where(self.data_grid.extra_orm_options)
129
+ else
130
+ self.data_grid.in_data = self.data_grid.in_data.limit(self.data_grid.per_page.to_i).offset(offset.to_i).where(filters).order(self.data_grid.initial_sort.blank? ? '' : "#{self.data_grid.initial_sort}").where(self.data_grid.extra_orm_options)
131
+ end
132
+
133
+ # prepare out data array, eval lambdas
134
+ self.data_grid.in_data.each_with_index do |obj, row_index|
135
+ row = []
136
+ self.data_grid.columns.each do |col|
137
+ if col.field.class == Symbol
138
+ if col.field == :auto
139
+ row << row_index + 1 + (self.data_grid.page-1)*self.data_grid.per_page
140
+ else
141
+ row << obj.send(col.field)
142
+ end
143
+ else
144
+ row << col.field.call(obj, self.data_grid.view_context)
145
+ end
146
+ end
147
+
148
+ # Hidden rows
149
+ unless self.data_grid.hidden_row.nil?
150
+ self.data_grid.out_hidden_rows << obj.send(self.data_grid.hidden_row)
151
+ end
152
+
153
+ self.data_grid.out_data << row
154
+ end
155
+
156
+ self.data_grid.pages = (self.data_grid.total/self.data_grid.per_page.to_f).ceil
157
+ end
158
+
159
+ # Prepare data for filters
160
+ def prepare_orm_data_for_filters
161
+ self.data_grid.columns.each do |col|
162
+ next if col.filter.nil? # if no filter
163
+
164
+ # Prepare auto filters
165
+ if col.filter == :auto
166
+ col.filter_data = self.data_grid.data_class.select("DISTINCT (#{col.filter_by}) as fc").to_a.to_a.map(&:fc)
167
+ end
168
+
169
+ col.filter_data.uniq!
170
+ col.filter_data.sort!
171
+ end
172
+ end
173
+
174
+ # Summary
175
+ def summary_orm
176
+ if self.data_grid.summary?
177
+ self.data_grid.summaries = []
178
+ self.data_grid.columns.each_with_index do |col, col_index|
179
+ if col.summary
180
+ column_data = []
181
+ self.data_grid.out_data.each do |row|
182
+ column_data << row[col_index]
183
+ end
184
+
185
+ self.data_grid.summaries[col_index] = DataGrid::Summaries.send(col.summary, column_data)
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ # Global Summary
192
+ def global_summary_orm
193
+ if self.data_grid.global_summary?
194
+ # prepare filters as ActiveRecord conditions
195
+ filters = prepare_orm_filters
196
+
197
+ self.data_grid.global_summaries = []
198
+ self.data_grid.columns.each_with_index do |col, col_index|
199
+ if col.global_summary
200
+ self.data_grid.global_summaries[col_index] = self.data_grid.in_data.scoped(:conditions => filters).where(self.data_grid.extra_orm_options).send(*col.global_summary)
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+
@@ -0,0 +1,19 @@
1
+ module DataGrid
2
+ class Engine < Rails::Engine
3
+
4
+ initializer "data_grid.action_controller" do
5
+ ActiveSupport.on_load(:action_controller) do
6
+ include DataGrid::Controller
7
+ end
8
+ end
9
+
10
+ initializer "data_grid.view_helpers" do
11
+ ActionView::Base.send :include, DataGrid::ViewHelpers
12
+ end
13
+
14
+ initializer "static assets" do |app|
15
+ app.middleware.use ::ActionDispatch::Static, "#{root}/public"
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ # Methods defined in this module are available as summary in DataGrid
2
+
3
+ module DataGrid
4
+ # Grid summaries
5
+ class Summaries
6
+
7
+ def self.average(a)
8
+ result = 0
9
+ unless a.blank?
10
+ a.each{|p| result += p.to_f}
11
+ result /= a.size
12
+ end
13
+ result.to_s
14
+ end
15
+
16
+ def self.sum(a)
17
+ result = 0
18
+ a.each{|p| result += p.to_f} unless a.blank?
19
+ result.to_s
20
+ end
21
+
22
+ def self.sum_price(a)
23
+ result = 0
24
+ unless a.blank?
25
+ a.each do |p|
26
+ result += p.match(/\-*\d+\,\d+/)[0].gsub(',', '.').to_f if p.match(/\d+\,\d+/) and p.match(/\d+\,\d+/)[0]
27
+ end
28
+ end
29
+ result = sprintf("%.2f", result.to_f.round(2)).to_s
30
+ result
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,3 @@
1
+ module DataGrid
2
+ VERSION = "0.0.2"
3
+ end