data_grid 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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