netzke-basepack 0.7.0 → 0.7.1

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 (169) hide show
  1. data/CHANGELOG.rdoc +9 -1
  2. data/README.md +5 -8
  3. data/Rakefile +0 -1
  4. data/lib/netzke/active_record/attributes.rb +13 -5
  5. data/lib/netzke/basepack.rb +0 -1
  6. data/lib/netzke/basepack/data_accessor.rb +76 -17
  7. data/lib/netzke/basepack/form_panel.rb +23 -34
  8. data/lib/netzke/basepack/form_panel/fields.rb +7 -0
  9. data/lib/netzke/basepack/form_panel/services.rb +6 -3
  10. data/lib/netzke/basepack/grid_panel/services.rb +2 -49
  11. data/lib/netzke/basepack/version.rb +1 -1
  12. data/netzke-basepack.gemspec +158 -154
  13. data/test/{rails_app → basepack_test_app}/.gitignore +2 -1
  14. data/test/basepack_test_app/.rvmrc +1 -0
  15. data/test/{rails_app → basepack_test_app}/Gemfile +2 -3
  16. data/test/{rails_app → basepack_test_app}/Gemfile.lock +80 -70
  17. data/test/{rails_app → basepack_test_app}/README +0 -0
  18. data/test/{rails_app → basepack_test_app}/Rakefile +0 -0
  19. data/test/{rails_app → basepack_test_app}/app/components/author_form.rb +0 -0
  20. data/test/{rails_app → basepack_test_app}/app/components/author_grid.rb +0 -0
  21. data/test/{rails_app → basepack_test_app}/app/components/book_form.rb +3 -2
  22. data/test/{rails_app → basepack_test_app}/app/components/book_form_with_custom_fields.rb +0 -0
  23. data/test/basepack_test_app/app/components/book_form_with_defaults.rb +8 -0
  24. data/test/{rails_app → basepack_test_app}/app/components/book_form_with_nested_attributes.rb +0 -0
  25. data/test/{rails_app → basepack_test_app}/app/components/book_grid.rb +0 -0
  26. data/test/{rails_app → basepack_test_app}/app/components/book_grid_loader.rb +0 -0
  27. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_custom_columns.rb +0 -0
  28. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_default_values.rb +0 -0
  29. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_extra_feedback.rb +0 -0
  30. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_extra_filters.rb +0 -0
  31. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_nested_attributes.rb +0 -0
  32. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_paging.rb +0 -0
  33. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_persistence.rb +0 -0
  34. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_scoped_authors.rb +0 -0
  35. data/test/{rails_app → basepack_test_app}/app/components/book_grid_with_virtual_attributes.rb +1 -1
  36. data/test/{rails_app → basepack_test_app}/app/components/book_paging_form_panel.rb +0 -0
  37. data/test/{rails_app → basepack_test_app}/app/components/book_query_builder.rb +0 -0
  38. data/test/{rails_app → basepack_test_app}/app/components/book_search_panel.rb +0 -0
  39. data/test/{rails_app → basepack_test_app}/app/components/book_search_panel/javascripts/i18n_de.js +0 -0
  40. data/test/{rails_app → basepack_test_app}/app/components/book_with_custom_primary_key_grid.rb +0 -0
  41. data/test/{rails_app → basepack_test_app}/app/components/books_bound_to_author.rb +0 -0
  42. data/test/{rails_app → basepack_test_app}/app/components/double_book_grid.rb +0 -0
  43. data/test/basepack_test_app/app/components/extras/book_presentation.rb +20 -0
  44. data/test/{rails_app → basepack_test_app}/app/components/form_without_model.rb +0 -0
  45. data/test/{rails_app → basepack_test_app}/app/components/generic_user_form.rb +0 -0
  46. data/test/{rails_app → basepack_test_app}/app/components/lockable_book_form.rb +0 -0
  47. data/test/{rails_app → basepack_test_app}/app/components/lockable_user_form.rb +0 -0
  48. data/test/{rails_app → basepack_test_app}/app/components/paging_form_with_search.rb +0 -0
  49. data/test/{rails_app → basepack_test_app}/app/components/simple_accordion.rb +0 -0
  50. data/test/{rails_app → basepack_test_app}/app/components/simple_panel.rb +0 -0
  51. data/test/{rails_app → basepack_test_app}/app/components/simple_tab_panel.rb +0 -0
  52. data/test/{rails_app → basepack_test_app}/app/components/simple_window.rb +0 -0
  53. data/test/{rails_app → basepack_test_app}/app/components/simple_wrapper.rb +0 -0
  54. data/test/{rails_app → basepack_test_app}/app/components/some_accordion_panel.rb +0 -0
  55. data/test/{rails_app → basepack_test_app}/app/components/some_auth_app.rb +0 -0
  56. data/test/{rails_app → basepack_test_app}/app/components/some_border_layout.rb +0 -0
  57. data/test/{rails_app → basepack_test_app}/app/components/some_simple_app.rb +0 -0
  58. data/test/{rails_app → basepack_test_app}/app/components/some_tab_panel.rb +0 -0
  59. data/test/{rails_app → basepack_test_app}/app/components/user_form.rb +1 -1
  60. data/test/{rails_app → basepack_test_app}/app/components/user_form_with_default_fields.rb +0 -0
  61. data/test/{rails_app → basepack_test_app}/app/components/user_grid.rb +0 -0
  62. data/test/{rails_app → basepack_test_app}/app/components/user_grid_with_customized_form_fields.rb +0 -0
  63. data/test/{rails_app → basepack_test_app}/app/components/window_component_loader.rb +0 -0
  64. data/test/{rails_app → basepack_test_app}/app/controllers/application_controller.rb +0 -0
  65. data/test/basepack_test_app/app/controllers/components_controller.rb +10 -0
  66. data/test/basepack_test_app/app/controllers/welcome_controller.rb +9 -0
  67. data/test/basepack_test_app/app/helpers/application_helper.rb +8 -0
  68. data/test/{rails_app → basepack_test_app}/app/helpers/embedded_components_helper.rb +0 -0
  69. data/test/{rails_app → basepack_test_app}/app/models/address.rb +0 -0
  70. data/test/{rails_app → basepack_test_app}/app/models/author.rb +0 -0
  71. data/test/{rails_app → basepack_test_app}/app/models/book.rb +0 -0
  72. data/test/{rails_app → basepack_test_app}/app/models/book_with_custom_primary_key.rb +0 -0
  73. data/test/{rails_app → basepack_test_app}/app/models/role.rb +0 -0
  74. data/test/{rails_app → basepack_test_app}/app/models/user.rb +0 -0
  75. data/test/{rails_app → basepack_test_app}/app/presenters/forms/generic_user.rb +0 -0
  76. data/test/{rails_app → basepack_test_app}/app/views/components/loadable_window.html.erb +0 -0
  77. data/test/{rails_app → basepack_test_app}/app/views/components/simple_panel.html.erb +0 -0
  78. data/test/basepack_test_app/app/views/layouts/application.html.erb +12 -0
  79. data/test/{rails_app/app/views/layouts/application.html.erb → basepack_test_app/app/views/layouts/components.html.erb} +0 -0
  80. data/test/{rails_app → basepack_test_app}/app/views/layouts/nested.html.erb +0 -0
  81. data/test/basepack_test_app/app/views/welcome/index.html.erb +10 -0
  82. data/test/{rails_app → basepack_test_app}/config.ru +0 -0
  83. data/test/{rails_app → basepack_test_app}/config/application.rb +7 -0
  84. data/test/{rails_app → basepack_test_app}/config/boot.rb +0 -0
  85. data/test/{rails_app → basepack_test_app}/config/cucumber.yml +0 -0
  86. data/test/{rails_app → basepack_test_app}/config/database.yml.sample +0 -0
  87. data/test/{rails_app → basepack_test_app}/config/environment.rb +0 -0
  88. data/test/{rails_app → basepack_test_app}/config/environments/development.rb +1 -1
  89. data/test/{rails_app → basepack_test_app}/config/environments/production.rb +0 -0
  90. data/test/{rails_app → basepack_test_app}/config/environments/test.rb +0 -0
  91. data/test/{rails_app → basepack_test_app}/config/initializers/backtrace_silencers.rb +0 -1
  92. data/test/{rails_app → basepack_test_app}/config/initializers/inflections.rb +0 -0
  93. data/test/{rails_app → basepack_test_app}/config/initializers/mime_types.rb +0 -0
  94. data/test/{rails_app → basepack_test_app}/config/initializers/netzke.rb +1 -1
  95. data/test/{rails_app → basepack_test_app}/config/initializers/secret_token.rb +0 -0
  96. data/test/{rails_app → basepack_test_app}/config/initializers/session_store.rb +1 -1
  97. data/test/{rails_app → basepack_test_app}/config/locales/de.yml +0 -0
  98. data/test/{rails_app → basepack_test_app}/config/locales/es.yml +0 -0
  99. data/test/{rails_app → basepack_test_app}/config/routes.rb +0 -0
  100. data/test/basepack_test_app/db/development_structure.sql +88 -0
  101. data/test/{rails_app → basepack_test_app}/db/migrate/20100914104207_create_users.rb +0 -0
  102. data/test/{rails_app → basepack_test_app}/db/migrate/20100914104236_create_roles.rb +0 -0
  103. data/test/{rails_app → basepack_test_app}/db/migrate/20101026185816_create_authors.rb +0 -0
  104. data/test/{rails_app → basepack_test_app}/db/migrate/20101026190021_create_books.rb +0 -0
  105. data/test/{rails_app → basepack_test_app}/db/migrate/20110101143818_create_addresses.rb +0 -0
  106. data/test/{rails_app → basepack_test_app}/db/migrate/20110213213050_create_netzke_component_states.rb +0 -0
  107. data/test/{rails_app → basepack_test_app}/db/migrate/20110701070052_create_book_with_custom_primary_keys.rb +0 -0
  108. data/test/basepack_test_app/db/migrate/20110901114016_add_last_read_at_to_books.rb +9 -0
  109. data/test/{rails_app → basepack_test_app}/db/schema.rb +4 -2
  110. data/test/{rails_app → basepack_test_app}/db/seeds.rb +0 -0
  111. data/test/{rails_app → basepack_test_app}/features/accordion_panel.feature +0 -0
  112. data/test/{rails_app → basepack_test_app}/features/components_in_view.feature +0 -0
  113. data/test/{rails_app → basepack_test_app}/features/form_panel.feature +15 -0
  114. data/test/{rails_app → basepack_test_app}/features/grid_panel.feature +0 -0
  115. data/test/{rails_app → basepack_test_app}/features/grid_panel_with_custom_primary_key.feature +0 -0
  116. data/test/basepack_test_app/features/grid_sorting.feature +39 -0
  117. data/test/{rails_app → basepack_test_app}/features/i18n.feature +0 -0
  118. data/test/{rails_app → basepack_test_app}/features/nested_attributes.feature +0 -0
  119. data/test/{rails_app → basepack_test_app}/features/paging_form_panel.feature +0 -1
  120. data/test/{rails_app → basepack_test_app}/features/search_in_grid.feature +0 -0
  121. data/test/{rails_app → basepack_test_app}/features/simple_app.feature +0 -0
  122. data/test/{rails_app → basepack_test_app}/features/simple_panel.feature +0 -0
  123. data/test/{rails_app → basepack_test_app}/features/step_definitions/accordion_steps.rb +0 -0
  124. data/test/{rails_app → basepack_test_app}/features/step_definitions/ext_steps.rb +0 -0
  125. data/test/{rails_app → basepack_test_app}/features/step_definitions/form_panel_steps.rb +4 -7
  126. data/test/{rails_app → basepack_test_app}/features/step_definitions/generic_steps.rb +0 -0
  127. data/test/{rails_app → basepack_test_app}/features/step_definitions/grid_panel_steps.rb +28 -5
  128. data/test/{rails_app → basepack_test_app}/features/step_definitions/pickle_steps.rb +0 -0
  129. data/test/{rails_app → basepack_test_app}/features/step_definitions/web_steps.rb +0 -0
  130. data/test/{rails_app → basepack_test_app}/features/support/env.rb +2 -5
  131. data/test/{rails_app → basepack_test_app}/features/support/paths.rb +0 -0
  132. data/test/{rails_app → basepack_test_app}/features/support/pickle.rb +0 -0
  133. data/test/{rails_app → basepack_test_app}/features/support/selectors.rb +0 -0
  134. data/test/{rails_app → basepack_test_app}/features/tab_panel.feature +0 -0
  135. data/test/{rails_app → basepack_test_app}/features/validations_in_grid.feature +0 -0
  136. data/test/{rails_app → basepack_test_app}/features/virtual_attributes.feature +0 -0
  137. data/test/{rails_app → basepack_test_app}/features/window.feature +0 -0
  138. data/test/{rails_app → basepack_test_app}/lib/tasks/.gitkeep +0 -0
  139. data/test/{rails_app → basepack_test_app}/lib/tasks/cucumber.rake +0 -0
  140. data/test/{rails_app → basepack_test_app}/public/404.html +0 -0
  141. data/test/{rails_app → basepack_test_app}/public/422.html +0 -0
  142. data/test/{rails_app → basepack_test_app}/public/500.html +0 -0
  143. data/test/{rails_app → basepack_test_app}/public/favicon.ico +0 -0
  144. data/test/{rails_app → basepack_test_app}/public/images/header-deco.gif +0 -0
  145. data/test/{rails_app → basepack_test_app}/public/images/rails.png +0 -0
  146. data/test/{rails_app → basepack_test_app}/public/javascripts/application.js +0 -0
  147. data/test/{rails_app → basepack_test_app}/public/javascripts/controls.js +0 -0
  148. data/test/{rails_app → basepack_test_app}/public/javascripts/dragdrop.js +0 -0
  149. data/test/{rails_app → basepack_test_app}/public/javascripts/effects.js +0 -0
  150. data/test/{rails_app → basepack_test_app}/public/javascripts/prototype.js +0 -0
  151. data/test/{rails_app → basepack_test_app}/public/javascripts/rails.js +0 -0
  152. data/test/{rails_app → basepack_test_app}/public/robots.txt +0 -0
  153. data/test/{rails_app → basepack_test_app}/public/stylesheets/.gitkeep +0 -0
  154. data/test/{rails_app → basepack_test_app}/script/cucumber +0 -0
  155. data/test/{rails_app → basepack_test_app}/script/rails +0 -0
  156. data/test/{rails_app → basepack_test_app}/spec/active_record/attributes_spec.rb +0 -0
  157. data/test/{rails_app → basepack_test_app}/spec/active_record/relation_extensions_spec.rb +0 -0
  158. data/test/{rails_app → basepack_test_app}/spec/components/form_panel_spec.rb +0 -0
  159. data/test/{rails_app → basepack_test_app}/spec/components/grid_panel_spec.rb +0 -0
  160. data/test/{rails_app → basepack_test_app}/spec/factories.rb +0 -0
  161. data/test/{rails_app → basepack_test_app}/spec/spec_helper.rb +0 -0
  162. data/test/{rails_app → basepack_test_app}/test/performance/browsing_test.rb +0 -0
  163. data/test/{rails_app → basepack_test_app}/test/test_helper.rb +0 -0
  164. data/test/{rails_app → basepack_test_app}/vendor/plugins/.gitkeep +0 -0
  165. metadata +198 -207
  166. data/test/rails_app/app/components/book_presentation.rb +0 -18
  167. data/test/rails_app/app/controllers/components_controller.rb +0 -6
  168. data/test/rails_app/app/controllers/welcome_controller.rb +0 -5
  169. data/test/rails_app/app/helpers/application_helper.rb +0 -2
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,11 @@
1
+ = 0.7.1 - 2011-09-04
2
+ * bug fix
3
+ * fixing the netzke_load endpoint when association fields are present
4
+ * dates were not displayed in date fields, and submitting a form with date fields might result in erasing those fields
5
+
6
+ * Rails 3.1 compatibility
7
+ * no meta_where dependencies (searching and filtering done with Arel)
8
+
1
9
  = 0.7.0 - 2011-08-09
2
10
  * Core 0.7.0 and Ext 4 compatibility
3
11
  * API changes
@@ -6,7 +14,7 @@
6
14
  = v0.6.5 - to be released
7
15
  * enhancements
8
16
  * When columns states are saved in the persistent storage, adding/removing columns (e.g. in the code) will reset the saved states
9
- * Moved features and specs to test/rails_app
17
+ * Moved features and specs to test/basepack_test_app
10
18
  * bug fix
11
19
  * FormPanel with multiple association fields wouldn't submit data correctly
12
20
  * GridPanel's forms take over the +text+ configuration option for columns as +fieldLabel+ for default fields
data/README.md CHANGED
@@ -24,7 +24,7 @@ Embed a basepack component into a view as any other Netzke component, e.g.:
24
24
 
25
25
  <%= netzke :books, :class_name => 'Netzke::Basepack::GridPanel', :model => 'Book' %>
26
26
 
27
- For more examples, see http://demo.netzke.com, and look into test/rails_app.
27
+ For more examples, see http://demo.netzke.com, and look into test/basepack_test_app.
28
28
 
29
29
  ## Testing and playing with Netzke Basepack
30
30
 
@@ -32,13 +32,9 @@ Netzke Basepack is bundled with Cucumber and RSpec tests. If you would like to c
32
32
 
33
33
  Besides, the bundled test application is a convenient [playground](https://github.com/skozlov/netzke-core/wiki/Playground) for those who search to experiment with the framework.
34
34
 
35
- After setting up the test application, you can access the test components (from test/rails_app/app/components) like this:
35
+ After starting up the test app, you can see the list of functional test components on the index page (along with links to the source code):
36
36
 
37
- http://localhost:3000/components/<name_of_the_test_component_class>
38
-
39
- e.g.:
40
-
41
- http://localhost:3000/components/UserGrid
37
+ http://localhost:3000/
42
38
 
43
39
  ## Icons support
44
40
  Netzke Basepack can make use of FamFamFam Silk icon set (http://www.famfamfam.com/archive/silk-icons-thats-your-lot/). To enable this, download the icons and put the "icons" folder into your app's public/images folder. Then restart your application.
@@ -55,9 +51,10 @@ Official project site: http://netzke.org
55
51
  Twitter:
56
52
 
57
53
  * latest news about Netzke: http://twitter.com/netzke
58
- * author's rambling about osx, productivity and what not: http://twitter.com/nomadcoder
54
+ * author's tweets on osx, productivity and what not: http://twitter.com/nomadcoder
59
55
 
60
56
  Many (if a bit outdated) tutorials: http://blog.writelesscode.com
61
57
 
62
58
  ---
63
59
  Copyright (c) 2008-2011 NomadCoder, released under the MIT license
60
+ Note, that Ext JS itself is licensed [differently](http://www.sencha.com/products/extjs/license/)
data/Rakefile CHANGED
@@ -10,7 +10,6 @@ begin
10
10
  gemspec.homepage = "http://netzke.org"
11
11
  gemspec.authors = ["Sergei Kozlov"]
12
12
  gemspec.add_dependency("netzke-core", "~>0.7.0")
13
- gemspec.add_dependency("meta_where", "~>1.0.0")
14
13
  gemspec.add_dependency("will_paginate", "~>3.0.0")
15
14
  gemspec.add_dependency("acts_as_list", "~>0.1.4")
16
15
  gemspec.post_install_message = <<-MESSAGE
@@ -104,10 +104,10 @@ module Netzke
104
104
  c = {:name => name, :attr_type => columns_hash[name].type}
105
105
 
106
106
  # If it's named as foreign key of some association, then it's an association column
107
- assoc = reflect_on_all_associations.detect{|a| a.primary_key_name == c[:name]}
107
+ assoc = reflect_on_all_associations.detect { |a| foreign_key_for_assoc(a) == c[:name] }
108
108
 
109
109
  if assoc && !assoc.options[:polymorphic]
110
- candidates = %w{name title label} << assoc.primary_key_name
110
+ candidates = %w{name title label} << foreign_key_for_assoc(assoc)
111
111
  assoc_method = candidates.detect{|m| (assoc.klass.instance_methods.map(&:to_s) + assoc.klass.column_names).include?(m) }
112
112
  c[:name] = "#{assoc.name}__#{assoc_method}"
113
113
  c[:attr_type] = assoc.klass.columns_hash[assoc_method].try(:type) || :string # when it's an instance method rather than a column, fall back to :string
@@ -127,6 +127,11 @@ module Netzke
127
127
  ).reject { |attr| netzke_excluded_attributes.include?(attr[:name]) }
128
128
  end
129
129
 
130
+ # Returns foreign key for given association (Rails >= 3.0)
131
+ def foreign_key_for_assoc(assoc)
132
+ assoc.respond_to?(:foreign_key) ? assoc.foreign_key : assoc.primary_key_name
133
+ end
134
+
130
135
  def association_attr?(attr_name)
131
136
  !!attr_name.index("__") # probably we can't do much better than this, as we don't know at this moment if the associated model has a specific attribute, and we don't really want to find it out
132
137
  end
@@ -169,7 +174,7 @@ module Netzke
169
174
  if r.respond_to?(m)
170
175
  r.send(m)
171
176
  else
172
- logger.debug "!!! Netzke::Basepack: Wrong attribute name: #{a[:name]}" unless r.nil?
177
+ logger.debug "Netzke::Basepack: Wrong attribute name: #{a[:name]}" unless r.nil?
173
178
  nil
174
179
  end
175
180
  end
@@ -180,11 +185,14 @@ module Netzke
180
185
 
181
186
  # a work-around for to_json not taking the current timezone into account when serializing ActiveSupport::TimeWithZone
182
187
  v = v.to_datetime.to_s(:db) if v.is_a?(ActiveSupport::TimeWithZone)
188
+
183
189
  v
184
190
  end
185
191
 
186
192
  # Assigns new value to an (association) attribute
187
193
  def set_value_for_attribute(a, v)
194
+ v = v.to_time_in_current_zone if v.is_a?(Date) # convert Date to Time
195
+
188
196
  if a[:setter]
189
197
  a[:setter].call(self, v)
190
198
  elsif respond_to?("#{a[:name]}=")
@@ -215,10 +223,10 @@ module Netzke
215
223
  self.send("#{assoc.options[:foreign_key] || assoc.name.to_s.foreign_key}=", v)
216
224
  end
217
225
  else
218
- logger.debug "!!! Netzke::Basepack: Association #{assoc} is not known for class #{self.class.name}"
226
+ logger.debug "Netzke::Basepack: Association #{assoc} is not known for class #{self.class.name}"
219
227
  end
220
228
  else
221
- logger.debug "!!! Netzke::Basepack: Wrong attribute name: #{a[:name]}"
229
+ logger.debug "Netzke::Basepack: Wrong attribute name: #{a[:name]}"
222
230
  end
223
231
  end
224
232
  end
@@ -2,7 +2,6 @@ require 'netzke/basepack/version'
2
2
 
3
3
  if defined? ActiveRecord
4
4
  require 'netzke/active_record'
5
- require 'meta_where'
6
5
  end
7
6
 
8
7
  # will_paginate supports more than just ActiveRecord
@@ -108,57 +108,116 @@ module Netzke
108
108
  end
109
109
 
110
110
  # An ActiveRecord::Relation instance encapsulating all the necessary conditions.
111
- # Using the meta_where magic.
112
111
  def get_relation(params = {})
113
- # make params coming from Ext grid filters understandable by meta_where
114
- conditions = params[:filter] && convert_filters(params[:filter]) || {}
112
+ @arel = data_class.arel_table
115
113
 
116
- relation = data_class.where(conditions)
114
+ relation = data_class.scoped
115
+
116
+ relation = apply_column_filters(relation, params[:filter]) if params[:filter]
117
117
 
118
118
  if params[:extra_conditions]
119
119
  extra_conditions = normalize_extra_conditions(ActiveSupport::JSON.decode(params[:extra_conditions]))
120
120
  relation = relation.extend_with_netzke_conditions(extra_conditions) if params[:extra_conditions]
121
121
  end
122
122
 
123
- if params[:query]
123
+ query = params[:query] && ActiveSupport::JSON.decode(params[:query])
124
+
125
+ if query.present?
124
126
  # array of arrays of conditions that should be joined by OR
125
- query = ActiveSupport::JSON.decode(params[:query])
126
- meta_where = query.map do |conditions|
127
- normalize_and_conditions(conditions)
127
+ and_predicates = query.map do |conditions|
128
+ predicates_for_and_conditions(conditions)
128
129
  end
129
130
 
130
131
  # join them by OR
131
- meta_where = meta_where.inject(meta_where.first){ |r,c| r | c } if meta_where.present?
132
+ predicates = and_predicates[1..-1].inject(and_predicates.first){ |r,c| r.or(c) }
132
133
  end
133
134
 
134
- relation = relation.where(meta_where)
135
+ relation = relation.where(predicates)
135
136
 
136
137
  relation = relation.extend_with(config[:scope]) if config[:scope]
137
138
 
138
139
  relation
139
140
  end
140
141
 
142
+ # Parses and applies grid column filters, calling consequent "where" methods on the passed relation.
143
+ # Returns the updated relation.
144
+ #
145
+ # Example column grid data:
146
+ #
147
+ # {"0" => {
148
+ # "data" => {
149
+ # "type" => "numeric",
150
+ # "comparison" => "gt",
151
+ # "value" => 10 },
152
+ # "field" => "id"
153
+ # },
154
+ # "1" => {
155
+ # "data" => {
156
+ # "type" => "string",
157
+ # "value" => "pizza"
158
+ # },
159
+ # "field" => "food_name"
160
+ # }}
161
+ #
162
+ # This will result in:
163
+ #
164
+ # relation.where(["id > ?", 10]).where(["food_name like ?", "%pizza%"])
165
+ def apply_column_filters(relation, column_filter)
166
+ res = relation
167
+ operator_map = {"lt" => "<", "gt" => ">"}
168
+
169
+ # these are still JSON-encoded due to the migration to Ext.direct
170
+ column_filter=JSON.parse(column_filter)
171
+ column_filter.each do |v|
172
+ assoc, method = v["field"].split('__')
173
+ if method
174
+ assoc = data_class.reflect_on_association(assoc.to_sym)
175
+ field = [assoc.klass.table_name, method].join('.').to_sym
176
+ else
177
+ field = assoc.to_sym
178
+ end
179
+
180
+ value = v["value"]
181
+
182
+ op = operator_map[v['comparison']]
183
+
184
+ case v["type"]
185
+ when "string"
186
+ res = res.where(["#{field} like ?", "%#{value}%"])
187
+ when "numeric", "date"
188
+ res = res.where(["#{field} #{op} ?", value])
189
+ else
190
+ res = res.where(["#{field} = ?", value])
191
+ end
192
+ end
193
+
194
+ res
195
+ end
196
+
197
+
141
198
  protected
142
199
 
143
- def normalize_and_conditions(conditions)
144
- and_conditions = conditions.map do |q|
200
+ def predicates_for_and_conditions(conditions)
201
+ return nil if conditions.empty?
202
+
203
+ predicates = conditions.map do |q|
145
204
  value = q["value"]
146
205
  case q["operator"]
147
206
  when "contains"
148
- q["attr"].to_sym.matches % %Q{%#{value}%}
207
+ @arel[q["attr"]].matches "%#{value}%"
149
208
  else
150
209
  if value == false || value == true
151
- q["attr"].to_sym.eq % (value ? 1 : 0)
210
+ @arel[q["attr"]].eq(value ? 1 : 0)
152
211
  else
153
- q["attr"].to_sym.send(q["operator"]) % value
212
+ @arel[q["attr"]].send(q["operator"], value)
154
213
  end
155
214
  end
156
215
  end
157
216
 
158
217
  # join them by AND
159
- and_conditions.inject(and_conditions.first){ |r,c| r & c } if and_conditions.present?
218
+ predicates[1..-1].inject(predicates.first){ |r,p| r.and(p) }
160
219
  end
161
220
 
162
221
  end
163
222
  end
164
- end
223
+ end
@@ -6,7 +6,8 @@ module Netzke
6
6
  module Basepack
7
7
  # Ext.form.Panel-based component
8
8
  #
9
- # == Configuration
9
+ # == Netzke-specific config options
10
+ #
10
11
  # * +model+ - name of the ActiveRecord model that provides data to this GridPanel.
11
12
  # * +record+ - record to be displayd in the form. Takes precedence over +:record_id+
12
13
  # * +record_id+ - id of the record to be displayd in the form. Also see +:record+
@@ -14,10 +15,20 @@ module Netzke
14
15
  # * +mode+ - render mode, accepted options:
15
16
  # * +lockable+ - makes the form panel load initially in "display mode", then lets "unlock" it, change the values, and "lock" it again, while updating the values on the server
16
17
  # * +updateMask+ - +Ext.LoadMask+ config options for the mask shown while the form is submitting its values
17
- # Besides, FormPanel can accept any meaninful :
18
18
  #
19
19
  # === Layout configuration
20
+ #
20
21
  # The layout of the form is configured by supplying the +item+ config option, same way it would be configured in Ext (thus allowing for complex form layouts). FormPanel will expand fields by looking at their names (unless +no_binding+ set to +true+ is specified for a specific field).
22
+ #
23
+ # == Endpoints
24
+ # FormPanel implements the following endpoints:
25
+ #
26
+ # * +netzke_load+ - loads a record with a given id from the server, e.g.:
27
+ #
28
+ # someFormPanel.netzkeLoad({id: 100});
29
+ #
30
+ # * +netzke_submit+ - gets called when the form gets submitted (e.g. by pressing the Apply button, or by calling onApply)
31
+ # * +get_combobox_options+ - gets called when a 'remote' combobox field gets expanded
21
32
  class FormPanel < Netzke::Base
22
33
 
23
34
  js_base_class "Ext.form.Panel"
@@ -94,44 +105,22 @@ module Netzke
94
105
 
95
106
  # A hash of record data including the meta field
96
107
  def js_record_data
97
- record.to_hash(fields).merge(:_meta => meta_field).literalize_keys
108
+ hsh = record.to_hash(fields).merge(:_meta => meta_field).literalize_keys
109
+
110
+ # HACK: a dirty hack cutting off the time part from the datetime string to please the form's datefield - until we have a real datetimefield
111
+ hsh.each_pair do |k,v|
112
+ if v && [:datetime, :date].include?(fields[k.to_sym].try(:fetch, :attr_type, nil))
113
+ hsh[k] = v.split.first
114
+ end
115
+ end
116
+
117
+ hsh
98
118
  end
99
119
 
100
120
  def record
101
121
  @record ||= config[:record] || config[:record_id] && data_class && data_class.where(data_class.primary_key => config[:record_id]).first
102
122
  end
103
123
 
104
- # def configuration_components
105
- # res = []
106
- #
107
- # res << {
108
- # :name => 'fields',
109
- # :class_name => "FieldsConfigurator",
110
- # :active => true,
111
- # :owner => self,
112
- # :persistent_config => true
113
- # }
114
- #
115
- # res << {
116
- # :name => 'general',
117
- # :class_name => "PropertyEditor",
118
- # :component => self,
119
- # :title => false
120
- # }
121
- #
122
- # res
123
- # end
124
-
125
- def self.property_fields
126
- res = [
127
- {:name => "ext_config__title", :attr_type => :string},
128
- {:name => "ext_config__header", :attr_type => :boolean, :default => true},
129
- {:name => "ext_config__bbar", :attr_type => :json}
130
- ]
131
-
132
- res
133
- end
134
-
135
124
  private
136
125
 
137
126
  def self.server_side_config_options
@@ -100,6 +100,12 @@ module Netzke
100
100
  set_default_field_xtype(field) if field[:xtype].nil?
101
101
  set_default_read_only(field)
102
102
 
103
+ # temporal datetime setup, while we don't have real datetime field
104
+ if field[:attr_type] == :datetime || field[:attr_type] == :date
105
+ field[:format] ||= "Y-m-d" # needed for
106
+ field[:submit_format] = "Y-m-d"
107
+ end
108
+
103
109
  # provide our special combobox with our id
104
110
  field[:parent_id] = self.global_id if field[:xtype] == :netzkeremotecombo
105
111
 
@@ -183,6 +189,7 @@ module Netzke
183
189
  :date => :datefield,
184
190
  # WIP: waiting for datetime.js implementation for ExtJS 4
185
191
  # :datetime => :datetimefield,
192
+ :datetime => :datefield,
186
193
 
187
194
  :text => :textarea,
188
195
  :json => :jsonfield,
@@ -8,14 +8,18 @@ module Netzke
8
8
 
9
9
  #
10
10
  # Endpoints
11
- #
11
+
12
+ # Called when the form gets submitted (e.g. by pressing the Apply button)
12
13
  endpoint :netzke_submit, :pre => true do |params|
13
14
  netzke_submit(params)
14
15
  end
15
16
 
17
+ # Can be called when the form needs to load a record with given ID. E.g.:
18
+ #
19
+ # someForm.netzkeLoad({id: 100});
16
20
  endpoint :netzke_load do |params|
17
21
  @record = data_class && data_class.find_by_id(params[:id])
18
- {:set_form_values => @record.to_hash(fields)}
22
+ {:set_form_values => js_record_data}
19
23
  end
20
24
 
21
25
  # Returns options for a combobox
@@ -98,7 +102,6 @@ module Netzke
98
102
 
99
103
  # Creates/updates a record from hash
100
104
  def create_or_update_record(hsh)
101
-
102
105
  hsh.merge!(config[:strong_default_attrs]) if config[:strong_default_attrs]
103
106
  @record ||= data_class.find(:first, :conditions => {data_class.primary_key => hsh.delete(data_class.primary_key)}) # only pick up the record specified in the params if it was not provided in the configuration
104
107
  success = true
@@ -214,10 +214,10 @@ module Netzke
214
214
  relation = relation.send(column[:sorting_scope].to_sym, dir.to_sym)
215
215
  else
216
216
  relation = if method.nil?
217
- relation.order(assoc.to_sym.send(dir))
217
+ relation.order("#{assoc} #{dir}")
218
218
  else
219
219
  assoc = data_class.reflect_on_association(assoc.to_sym)
220
- relation.order(assoc.klass.table_name.to_sym => method.to_sym.send(dir)).joins(assoc.name)
220
+ relation.joins(assoc.name).order("#{assoc.klass.table_name}.#{method} #{dir}")
221
221
  end
222
222
  end
223
223
  end
@@ -298,53 +298,6 @@ module Netzke
298
298
  mod_records
299
299
  end
300
300
 
301
- # Converts Ext.ux.grid.GridFilters filters to searchlogic conditions, e.g.
302
- # {"0" => {
303
- # "data" => {
304
- # "type" => "numeric",
305
- # "comparison" => "gt",
306
- # "value" => 10 },
307
- # "field" => "id"
308
- # },
309
- # "1" => {
310
- # "data" => {
311
- # "type" => "string",
312
- # "value" => "pizza"
313
- # },
314
- # "field" => "food_name"
315
- # }}
316
- #
317
- # =>
318
- #
319
- # metawhere: :id.gt => 100, :food_name.matches => '%pizza%'
320
- def convert_filters(column_filter)
321
- # these are still JSON-encoded due to the migration to Ext.direct
322
- column_filter=JSON.parse(column_filter)
323
- res = {}
324
- column_filter.each do |v|
325
- assoc, method = v["field"].split('__')
326
- if method
327
- assoc = data_class.reflect_on_association(assoc.to_sym)
328
- field = [assoc.klass.table_name, method].join('.').to_sym
329
- else
330
- field = assoc.to_sym
331
- end
332
-
333
- value = v["value"]
334
-
335
- case v["type"]
336
- when "string"
337
- op = v['comparison'] && (v['comparison'] == 'like' ? :matches : :does_not_match) || :matches
338
- field = field.send(op)
339
- value = "%#{value}%"
340
- when "numeric", "date"
341
- field = field.send :"#{v['comparison']}"
342
- end
343
- res.merge!({field => value})
344
- end
345
- res
346
- end
347
-
348
301
  def normalize_extra_conditions(conditions)
349
302
  conditions.each_pair do |k,v|
350
303
  conditions[k] = "%#{v}%" if ["like", "matches"].include?(k.to_s.split("__").last)