fancygrid 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/CHANGELOG +9 -2
  2. data/Gemfile +6 -9
  3. data/Gemfile.lock +88 -103
  4. data/README.md +226 -0
  5. data/ROADMAP +0 -1
  6. data/Rakefile +2 -2
  7. data/VERSION +1 -1
  8. data/app/views/fancygrid/controls.html.haml +34 -0
  9. data/app/views/fancygrid/fancygrid.html.haml +18 -0
  10. data/app/views/fancygrid/search.html.haml +24 -0
  11. data/app/views/fancygrid/sort.html.haml +8 -0
  12. data/app/views/fancygrid/table.html.haml +25 -0
  13. data/config/locales/fancygrid.de.yml +17 -19
  14. data/config/locales/fancygrid.en.yml +14 -17
  15. data/fancygrid.gemspec +48 -88
  16. data/lib/assets/javascripts/fancygrid.js +425 -0
  17. data/lib/assets/javascripts/fancygrid.min.js +15 -0
  18. data/lib/assets/stylesheets/fancygrid.css +177 -0
  19. data/lib/fancygrid.rb +63 -44
  20. data/lib/fancygrid/column.rb +165 -0
  21. data/lib/fancygrid/controller/helper.rb +46 -0
  22. data/lib/fancygrid/grid.rb +171 -317
  23. data/lib/fancygrid/node.rb +85 -490
  24. data/lib/fancygrid/object_wrapper.rb +24 -0
  25. data/lib/fancygrid/orm/active_record.rb +39 -0
  26. data/lib/fancygrid/orm/sql_generator.rb +127 -0
  27. data/lib/fancygrid/view/helper.rb +44 -0
  28. data/lib/fancygrid/view_state.rb +161 -0
  29. data/spec/column_spec.rb +29 -0
  30. data/spec/dummy/app/controllers/application_controller.rb +48 -0
  31. data/spec/dummy/app/views/application/index.html.haml +11 -0
  32. data/spec/dummy/app/views/layouts/application.html.erb +1 -1
  33. data/spec/dummy/config/application.rb +1 -1
  34. data/spec/dummy/config/environments/development.rb +2 -2
  35. data/spec/dummy/config/environments/test.rb +2 -2
  36. data/spec/dummy/config/routes.rb +3 -2
  37. data/spec/dummy/db/development.sqlite3 +0 -0
  38. data/spec/dummy/db/schema.rb +26 -0
  39. data/spec/dummy/public/javascripts/jquery-1.4.2.js +6240 -0
  40. data/spec/dummy/public/javascripts/jquery-fancygrid.js +425 -0
  41. data/spec/dummy/public/javascripts/jquery-ui.js +41 -0
  42. data/spec/dummy/public/stylesheets/fancygrid.css +183 -0
  43. data/spec/node_spec.rb +79 -301
  44. data/spec/spec_helper.rb +0 -29
  45. data/spec/view_state_spec.rb +91 -0
  46. metadata +124 -137
  47. data/.bundle/config +0 -2
  48. data/README.rdoc +0 -299
  49. data/app/views/fancygrid/_cells.html.haml +0 -13
  50. data/app/views/fancygrid/base/controls.html.haml +0 -40
  51. data/app/views/fancygrid/base/list_frame.html.haml +0 -37
  52. data/app/views/fancygrid/base/search.html.haml +0 -33
  53. data/app/views/fancygrid/base/sort.html.haml +0 -20
  54. data/app/views/fancygrid/base/table_frame.html.haml +0 -45
  55. data/config/initializers/fancygrid.rb +0 -67
  56. data/lib/fancygrid/helper.rb +0 -129
  57. data/lib/fancygrid/query_generator.rb +0 -340
  58. data/lib/fancygrid/view.rb +0 -148
  59. data/lib/generators/install_generator.rb +0 -61
  60. data/lib/generators/views_generator.rb +0 -25
  61. data/lib/version.rb +0 -0
  62. data/public/images/fancygrid/add.png +0 -0
  63. data/public/images/fancygrid/clear.png +0 -0
  64. data/public/images/fancygrid/ddn.png +0 -0
  65. data/public/images/fancygrid/dn.png +0 -0
  66. data/public/images/fancygrid/dots.png +0 -0
  67. data/public/images/fancygrid/loading.gif +0 -0
  68. data/public/images/fancygrid/magnifier.png +0 -0
  69. data/public/images/fancygrid/next.png +0 -0
  70. data/public/images/fancygrid/order.png +0 -0
  71. data/public/images/fancygrid/prev.png +0 -0
  72. data/public/images/fancygrid/reload.png +0 -0
  73. data/public/images/fancygrid/remove.png +0 -0
  74. data/public/images/fancygrid/spacer.gif +0 -0
  75. data/public/images/fancygrid/submit.png +0 -0
  76. data/public/images/fancygrid/th_bg.png +0 -0
  77. data/public/images/fancygrid/up.png +0 -0
  78. data/public/images/fancygrid/uup.png +0 -0
  79. data/public/javascripts/fancygrid.js +0 -477
  80. data/public/javascripts/fancygrid.min.js +0 -17
  81. data/public/stylesheets/fancygrid.css +0 -289
  82. data/public/stylesheets/fancygrid.scss +0 -302
  83. data/spec/dummy/log/development.log +0 -0
  84. data/spec/dummy/log/production.log +0 -0
  85. data/spec/dummy/log/server.log +0 -0
  86. data/spec/dummy/log/test.log +0 -1026
  87. data/spec/dummy/public/javascripts/application.js +0 -2
  88. data/spec/dummy/public/javascripts/controls.js +0 -965
  89. data/spec/dummy/public/javascripts/dragdrop.js +0 -974
  90. data/spec/dummy/public/javascripts/effects.js +0 -1123
  91. data/spec/dummy/public/javascripts/prototype.js +0 -6001
  92. data/spec/dummy/public/javascripts/rails.js +0 -175
  93. data/spec/grid_spec.rb +0 -15
  94. data/spec/integration/navigation_spec.rb +0 -9
  95. data/spec/query_generator_spec.rb +0 -358
data/.bundle/config DELETED
@@ -1,2 +0,0 @@
1
- --- {}
2
-
data/README.rdoc DELETED
@@ -1,299 +0,0 @@
1
- = Fancygrid
2
- Fancygrid mades it easy to create and render tables for database records in rails.
3
- == Features
4
- * ActiveRecord and ActiveResource are supported
5
- * Ajax data fetch
6
- * Pagination
7
- * Simple search with LIKE condition
8
- * Complex search with 17 different conditions
9
- * Frontend column sorting
10
- * View state caching
11
- * May be rendered anywhere, not restricted to the index action
12
- * Column values may be attributes, methods or even custom blocks
13
- * Custom templates for column formatting
14
-
15
- = Requirements
16
- * jQuery >= 1.4.2
17
- * jQuery-ui (required if column sorting is wanted)
18
- * Rails 3
19
- * Haml
20
-
21
- = Installation
22
- In your gemfile
23
- gem 'fancygrid', :git => 'git://github.com/giniedp/fancygrid.git'
24
-
25
- or for specific tag
26
- gem 'fancygrid', :git => 'git://github.com/giniedp/fancygrid.git', :tag => "1.0.0-pre"
27
-
28
- Run
29
- bundle install
30
-
31
- and
32
- rails g fancygrid:install
33
-
34
- then follow the instructions
35
-
36
- = Getting started
37
-
38
- == Basic Setup
39
- In any controller in any action you can define a fancygrid for a specific model.
40
- A controller is the place where you define what data should be queried from
41
- the database and what columns will be visible. For example you could define
42
- a table for your users like this:
43
- === Example
44
- # UsersController
45
- def index
46
- # setup fancygrid to display users
47
- fancygrid_for :users do |user|
48
-
49
- # specify attributes to display
50
- user.attributes( :id, :username, :email )
51
-
52
- # specify the callback url for ajax loading
53
- user.url = users_path
54
-
55
- # finally call find with some customized find options
56
- user.find( :order => "users.created_at DESC" )
57
-
58
- end
59
- end
60
-
61
- In your View you have to render the fancygrid. Use the name that you have used
62
- in your controller
63
- === Example
64
- # app/views/users/index.html.haml
65
- = fancygrid :users
66
-
67
- == Static tables
68
- If you dont want to have an ajax table, you can set the data directly without
69
- providing a callback url.
70
- === Example
71
- def index
72
- fancygrid_for :users do |user|
73
-
74
- # ...
75
-
76
- # dont set the url and find options like in the first example
77
- # instead set the data directly
78
- user.data= User.find(:all)
79
-
80
- end
81
- end
82
-
83
- == Table names and model names
84
- Usually fancygrid takes the passed name and tries to resolve the models class
85
- and its database table name. If you need to use a name that is different
86
- from your models name which is the case when you have namespaced models, you can
87
- pass the models constant and its table name to fancygrid
88
- === Example
89
- def index
90
- fancygrid_for :user, Namespace::User, "users" do |user|
91
-
92
- # ...
93
-
94
- end
95
- end
96
-
97
- = Using methods on records
98
- You are not limited to the models attributes to display in the fancygrid. You can
99
- provide method names to display a models properties
100
- === Example
101
- def index
102
- fancygrid_for :users do |user|
103
-
104
- # ...
105
-
106
- # specify methods to call on each record
107
- user.methods(:full_name, :some_other_method)
108
-
109
- # ...
110
-
111
- end
112
- end
113
-
114
- You can even pass a proc to a single column
115
- === Example
116
- def index
117
- fancygrid_for :users do |user|
118
-
119
- # ...
120
-
121
- user.proc( :roles ) do |record|
122
- record.roles.map{ |r| r.name }.join(", ")
123
- end
124
-
125
- # ...
126
-
127
- end
128
- end
129
-
130
- For more complex output you must have to render a column with custom template
131
-
132
- == Rendering columns with templates
133
- For custom cell rendering create a template at some place like *app/views/fancygrid/users.html.haml*
134
- In your fancygrid definition do:
135
- === Example
136
- def index
137
- fancygrid_for :users do |user|
138
-
139
- # ...
140
-
141
- # specify cells that will be rendered with custom code
142
- user.rendered(:actions)
143
-
144
- # set the templates name
145
- user.template = "fancygrid/users"
146
-
147
- # ...
148
-
149
- end
150
- end
151
-
152
- In your template you can use the following locals: <tt>table</tt>, <tt>column</tt>, <tt>record</tt> and <tt>value</tt>
153
- so you can render your cell like this:
154
- === Example
155
- - case table.name
156
- - when :users
157
- - case column.name
158
- - when :actions
159
- = link_to "Show", user_path(record)
160
- = link_to "Edit", edit_user_path(record)
161
-
162
- == Rendering columns with a haml block
163
- In your view you can give a grid a block that should be used for rendering
164
- === Example
165
- = fancygrid(:users) do |column, record, value|
166
- - case column.name
167
- - when :actions
168
- = link_to "Show", user_path(record)
169
- = link_to "Edit", edit_user_path(record)
170
-
171
- == Display associated data (belongs_to or has_one)
172
- To display an associated data you have to build the nodes for that data and
173
- specify the include option for the find method
174
- === Example
175
- def index
176
- fancygrid_for :users do |user|
177
-
178
- # ...
179
-
180
- user.columns_for(:contact) do |contact|
181
- contact.attributes( :first_name, :last_name )
182
- end
183
-
184
- # ...
185
-
186
- user.find( :include => :contact )
187
-
188
- end
189
- end
190
-
191
- If your association name is different from the models name pass the model
192
- constant into the columns_for method.
193
- === Example
194
- def index
195
- fancygrid_for :users do |user|
196
-
197
- # ...
198
-
199
- user.columns_for(:work_address, Address) do |address|
200
- address.attributes( :street, :zipcode, :city )
201
- end
202
-
203
- # ...
204
-
205
- user.find( :include => :work_address )
206
-
207
- end
208
- end
209
-
210
- == Display associated data (has_many or has_and_belongs_to_many)
211
- Similar to the previous example you have to build the nodes for the associations
212
- and specify the include option
213
- === Example
214
- def index
215
- fancygrid_for :users do |user|
216
-
217
- # ...
218
-
219
- user.columns_for(:roles) do |roles|
220
- roles.attributes( :name )
221
- end
222
-
223
- # ...
224
-
225
- user.find( :unclude => :roles )
226
-
227
- end
228
- end
229
-
230
- However this would not work as expected. Its the same as calling <tt>user.roles.name</tt>
231
- which would call <tt>name</tt> on a collection of roles.
232
-
233
- Instead you should rather define a <tt>proc</tt> to return all role names or
234
- render that cell with custom code.
235
- === Example
236
- def index
237
- fancygrid_for :users do |user|
238
-
239
- # ...
240
-
241
- user.proc( :roles ) do |record|
242
- record.roles.map{ |r| r.name }.join(", ")
243
- end
244
-
245
- # ...
246
-
247
- end
248
- end
249
-
250
- == Order your conditions
251
- If you have a large condition to make or you want to use a condition that depends on a users role, for example when
252
- some of your users are not allowed to see specific data, then you can give the find method a block and use the query generator
253
-
254
- === Example
255
- fancygrid_for :users do |grid|
256
-
257
- # ...
258
-
259
- grid.find do |query|
260
- # all the conditions are joined with an AND operator
261
- query.conditions(["users.first_name = ?", "some name"])
262
- query.conditions(["users.last_name = ?", "some name"])
263
-
264
- # use other finder options as methods
265
- query.select #...
266
- query.order #...
267
- # ...
268
- end
269
- end
270
-
271
- == Caching the view state
272
- To make your users life easier you can enable the view state caching. This way
273
- the user can search for data, leave the site, come back and have his last
274
- search back on screen. Here is an example of how to store the view in the users session:
275
- === Example
276
- # ensure that there is a hash in the session
277
- session[:users_table_view_state] ||= {}
278
-
279
- fancygrid_for :users do |grid|
280
-
281
- # ...
282
-
283
- # specify a proc to load the view state
284
- grid.load_view_proc do |grid_instance|
285
- session["fancygrid_users"] || {}
286
- end
287
-
288
- # specify a proc to store the view state
289
- grid.store_view_proc do |grid_instance, dump|
290
- session["fancygrid_users"] = dump
291
- end
292
-
293
- end
294
-
295
- Its up to your business logic where and how you store the dumped view state. If you have lots of tables
296
- i would recommend to enable database session store.
297
-
298
- = Copyright
299
- Copyright (c) 2010 Alexander Graefenstein. See LICENSE for details.
@@ -1,13 +0,0 @@
1
- / available locals are
2
- / grid : the fancygrid instance
3
- / cell : the column to render
4
- / record : the datarecord for the current row to render
5
- / value : the value for current cell to render
6
-
7
- / example rendering the actions show and edit for a users table
8
- /- case grid.name
9
- /- when :users
10
- / - case cell.name
11
- / - when :actions
12
- / = link_to "Show", user_path(record)
13
- / = link_to "Edit", edit_user_path(record)
@@ -1,40 +0,0 @@
1
- %ul.fg-control-bar{ :class => css_class }
2
- %li
3
- %span
4
- = t(:"pagination.per_page", :default => "Results per Page", :scope => Fancygrid.i18n_scope)
5
- = select_tag(:per_page, options_for_select(fancygrid.per_page_options, fancygrid.view.get_pagination_per_page), :class => "fg-per-page")
6
-
7
- %li.separator
8
- %li.button
9
- = fancygrid_button(:"fg-previous", :"pagination.prev_page", "Previous page")
10
-
11
- %li
12
- %span
13
- = t(:"pagination.page", :default => "Page", :scope => Fancygrid.i18n_scope)
14
- = text_field_tag(:"fg-page", fancygrid.view.get_pagination_page + 1, :class => :"fg-page" )
15
- %span
16
- = t(:"pagination.of", :default => "of", :scope => Fancygrid.i18n_scope)
17
- %span.fg-page-total
18
- = 0
19
-
20
- %li.button
21
- = fancygrid_button(:"fg-next", :"pagination.next_page","Next page")
22
- %li.separator
23
- %li
24
- %span
25
- = t(:"pagination.results", :default => "Total entries", :scope => Fancygrid.i18n_scope)
26
- %span.fg-result-total
27
- = fancygrid.resultcount or 0
28
- %li.button
29
- = fancygrid_button(:"fg-reload", :"pagination.reload", "Reload")
30
- %li.button
31
- = fancygrid_button(:"fg-clear", :"search.clear", "Clear search")
32
- %li.button
33
- = fancygrid_button(:"fg-magnify", :"search.toggle", "Toggle Search")
34
-
35
- - if fancygrid.has_sort_window?
36
- %li.button
37
- = fancygrid_button(:"fg-sort", :"sort.submit", "Sort columns")
38
- %li.separator
39
-
40
- = yield :fancygrid_buttons
@@ -1,37 +0,0 @@
1
- .fg-fancygrid{ :class => fancygrid.name }
2
- - if fancygrid.has_complex_search?
3
- = render(:template => Fancygrid.search_template, :locals => { :fancygrid => fancygrid })
4
- - if fancygrid.has_top_control?
5
- = render(:template => Fancygrid.controls_template, :locals => { :fancygrid => fancygrid, :css_class => "controls top" })
6
-
7
- .fg-tablewrapper
8
- - unless fancygrid.is_static?
9
- %ul.fg-search
10
- - fancygrid.each_visible_leaf do |leaf|
11
- - next unless leaf.searchable
12
- %li{ :class => leaf.css_class }
13
- %label{ :for => leaf.tag_name }
14
- = leaf.human_name
15
- - case leaf.search_input_kind
16
- - when :none
17
- = text_field_tag( leaf.tag_name, leaf.search_value, :class => "fg-attribute" )
18
- - when :select
19
- = select_tag( leaf.tag_name, options_for_select(leaf.search_select_collection, :selected => leaf.search_value), :class => "fg-attribute" )
20
-
21
- %ul.fg-row
22
- - fancygrid.each_record do |record|
23
- %li{ :class => fancygrid.name.to_s.singularize }
24
- = render_fancygrid_leaf(record, fancygrid, &format_block)
25
-
26
- - if fancygrid.has_bottom_control?
27
- = render(:template => Fancygrid.controls_template, :locals => { :fancygrid => fancygrid, :css_class => "controls bottom" })
28
-
29
- - unless fancygrid.is_static?
30
- :javascript
31
- $(function(){
32
- var fancyOptions = #{fancygrid.js_options};
33
- $(".fg-fancygrid.#{fancygrid.name}").fancygrid(fancyOptions);
34
- if(!fancyOptions.isStatic){
35
- $(".fg-fancygrid.#{fancygrid.name}").fancygrid("reloadPage");
36
- }
37
- });
@@ -1,33 +0,0 @@
1
- :ruby
2
- searchable_columns = fancygrid.serachable_leafs.map{ |leaf|
3
- [leaf.human_name, leaf.tag_name]
4
- }
5
- search_operators = fancygrid.search_operators.map { |op|
6
- [I18n.t(:"search.operator.#{op.to_s}", :default => op.to_s.humanize, :scope => Fancygrid.i18n_scope ), op.to_s]
7
- }
8
-
9
- = field_set_tag( t(:"search.title", :default => "Search", :scope => Fancygrid.i18n_scope), :class => :"fg-search" ) do
10
- .fg-search-controls
11
- = fancygrid_button(:"fg-search-add", :"search.add", 'Add')
12
- = fancygrid_button(:"fg-search-submit", :"search.submit", 'Search')
13
- = fancygrid_button(:"fg-clear", :"search.clear", 'Clear search')
14
- = check_box_tag(:"fg-search-conditions", :all, fancygrid.view.get_search_operator.to_s == "all")
15
- = label_tag(:"fg-search-conditions", t(:"fancygrid.search.conditions", :default => 'All conditions must met:'))
16
-
17
- %ul.fg-search-criteria
18
- - fancygrid.each_visible_leaf do |leaf|
19
- - fancygrid.view.get_node_search_conditions(leaf).each do |condition|
20
- %li.fg-search-criterion
21
- = fancygrid_button(:"fg-search-remove", :"search.remove", "Remove")
22
- = select_tag(:column_name, options_for_select(searchable_columns, leaf.tag_name))
23
- = select_tag(:operator, options_for_select(search_operators, condition[:operator]))
24
- = text_field_tag(:column_value, condition[:value])
25
-
26
-
27
-
28
- .fg-search-template
29
- %li.fg-search-criterion
30
- = fancygrid_button(:"fg-search-remove", :"search.remove", "Remove")
31
- = select_tag(:column_name, options_for_select(searchable_columns))
32
- = select_tag(:operator, options_for_select(search_operators ))
33
- = text_field_tag(:column_value, "")
@@ -1,20 +0,0 @@
1
- .fg-sort-window.ui-widget-overlay{ :style => "display: none;" }
2
- .fg-sort-content{ :style => "display: none;" }
3
- .ui-state-highlight.ui-corner-all
4
- = t(:"sort.info", :scope => Fancygrid.i18n_scope)
5
- %ul.fg-sortable-visible.fg-sortable.ui-widget-content.ui-corner-all
6
- %li.fg-not-sortable.ui-corner-all.ui-state-active
7
- %h4
8
- = t(:"sort.header_visible", :scope => Fancygrid.i18n_scope)
9
- - fancygrid.each_visible_leaf do |leaf|
10
- %li.ui-state-default.ui-widget-header.ui-corner-all{ :class => leaf.css_class, :id => leaf.tag_name}
11
- %span.ui-icon.ui-icon-arrowthick-2-n-s
12
- = leaf.human_name
13
- %ul.fg-sortable-hidden.fg-sortable.ui-widget-content.ui-corner-all
14
- %li.fg-not-sortable.ui-corner-all.ui-state-active
15
- %h4
16
- = t(:"sort.header_hidden", :scope => Fancygrid.i18n_scope)
17
- - fancygrid.each_hidden_leaf do |leaf|
18
- %li.ui-state-default.ui-widget-header.ui-corner-all{ :class => leaf.css_class, :id => leaf.tag_name}
19
- %span.ui-icon.ui-icon-arrowthick-2-n-s
20
- = leaf.human_name