netzke-core 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. data/CHANGELOG.md +16 -1
  2. data/Gemfile +12 -0
  3. data/README.md +22 -15
  4. data/Rakefile +19 -38
  5. data/app/controllers/netzke_controller.rb +1 -79
  6. data/javascripts/ext.js +17 -13
  7. data/lib/netzke/base.rb +6 -2
  8. data/lib/netzke/core/action_config.rb +7 -0
  9. data/lib/netzke/core/actions.rb +6 -32
  10. data/lib/netzke/core/client_class.rb +1 -1
  11. data/lib/netzke/core/component_config.rb +1 -1
  12. data/lib/netzke/core/composition.rb +17 -111
  13. data/lib/netzke/core/config_to_dsl_delegator.rb +0 -7
  14. data/lib/netzke/core/configuration.rb +48 -0
  15. data/lib/netzke/core/dsl_support.rb +71 -0
  16. data/lib/netzke/core/dynamic_assets.rb +10 -1
  17. data/lib/netzke/core/embedding.rb +2 -2
  18. data/lib/netzke/core/html.rb +29 -0
  19. data/lib/netzke/core/javascript.rb +32 -26
  20. data/lib/netzke/core/railz/action_view_ext/ext.rb +2 -2
  21. data/lib/netzke/core/railz/controller_extensions.rb +96 -3
  22. data/lib/netzke/core/railz/routes.rb +14 -3
  23. data/lib/netzke/core/ruby_ext/array.rb +4 -18
  24. data/lib/netzke/core/ruby_ext/hash.rb +19 -25
  25. data/lib/netzke/core/ruby_ext/time_with_zone.rb +1 -1
  26. data/lib/netzke/core/ruby_ext.rb +0 -2
  27. data/lib/netzke/core/session.rb +8 -1
  28. data/lib/netzke/core/state.rb +3 -3
  29. data/lib/netzke/core/version.rb +1 -1
  30. data/lib/netzke/core.rb +15 -7
  31. data/lib/netzke-core.rb +2 -9
  32. data/tasks/app_test_tasks.rake +94 -0
  33. data/tasks/rake_helper.rb +51 -0
  34. data/test/core_test_app/README +2 -2
  35. data/test/core_test_app/app/assets/javascripts/expect/expect.js +1253 -0
  36. data/test/core_test_app/app/assets/javascripts/mocha/mocha.js +5340 -0
  37. data/test/core_test_app/app/assets/stylesheets/mocha/mocha.css +231 -0
  38. data/test/core_test_app/app/components/{component_with_actions.rb → actions.rb} +7 -9
  39. data/test/core_test_app/app/components/{some_composite.rb → composition.rb} +16 -5
  40. data/test/core_test_app/app/components/{component_with_custom_css → css_inclusion}/stylesheets/custom.css +2 -2
  41. data/test/core_test_app/app/components/css_inclusion.rb +12 -0
  42. data/test/core_test_app/app/components/{component_loader/javascripts/component_loader.js → dynamic_loading/javascripts/dynamic_loading.js} +9 -1
  43. data/test/core_test_app/app/components/{component_loader.rb → dynamic_loading.rb} +12 -5
  44. data/test/core_test_app/app/components/{server_caller/javascripts/server_caller.js → endpoints/javascripts/endpoints.js} +10 -6
  45. data/test/core_test_app/app/components/{server_caller.rb → endpoints.rb} +12 -8
  46. data/test/core_test_app/app/components/{extended_server_caller.rb → endpoints_extended.rb} +6 -4
  47. data/test/core_test_app/app/components/ext_direct/composite.rb +5 -1
  48. data/test/core_test_app/app/components/feedback.rb +26 -0
  49. data/test/core_test_app/app/components/haml_panel/html/body.html.haml +10 -0
  50. data/test/core_test_app/app/components/haml_panel/html/server_response.html.haml +3 -0
  51. data/test/core_test_app/app/components/haml_panel.rb +32 -0
  52. data/test/core_test_app/app/components/hello_world.rb +1 -0
  53. data/test/core_test_app/app/components/js_inclusion/javascripts/extra_one.js +2 -0
  54. data/test/core_test_app/app/components/js_inclusion/javascripts/extra_two.js +2 -0
  55. data/test/core_test_app/app/components/js_inclusion/javascripts/js_inclusion.js +5 -0
  56. data/test/core_test_app/app/components/{component_with_js_mixin → js_inclusion}/javascripts/method_set_one.js +0 -0
  57. data/test/core_test_app/app/components/{component_with_js_mixin → js_inclusion}/javascripts/method_set_two.js +0 -0
  58. data/test/core_test_app/app/components/{component_with_js_mixin.rb → js_inclusion.rb} +3 -3
  59. data/test/core_test_app/app/components/js_inclusion_extended/javascripts/some_method_set.js +5 -0
  60. data/test/core_test_app/app/components/js_inclusion_extended.rb +6 -0
  61. data/test/core_test_app/app/components/loaded_css_inclusion.rb +22 -0
  62. data/test/core_test_app/app/components/{localized_panel.rb → localization.rb} +5 -5
  63. data/test/core_test_app/app/components/localization_extended.rb +2 -0
  64. data/test/core_test_app/app/components/persistence.rb +60 -0
  65. data/test/core_test_app/app/components/persistence_with_shared_state.rb +7 -0
  66. data/test/core_test_app/app/components/plugin_with_actions.rb +24 -0
  67. data/test/core_test_app/app/components/plugin_with_components.rb +3 -3
  68. data/test/core_test_app/app/components/plugin_with_endpoints.rb +29 -0
  69. data/test/core_test_app/app/components/plugins.rb +9 -0
  70. data/test/core_test_app/app/components/{kinda_complex_component → ruby_modules}/basic_stuff.rb +1 -1
  71. data/test/core_test_app/app/components/{kinda_complex_component → ruby_modules}/extra_stuff.rb +3 -3
  72. data/test/core_test_app/app/components/{kinda_complex_component.rb → ruby_modules.rb} +1 -1
  73. data/test/core_test_app/app/components/scoped/deeply_scoped/scoping.rb +10 -0
  74. data/test/core_test_app/app/components/scoped/scoping.rb +8 -0
  75. data/test/core_test_app/app/components/scoped/scoping_extended.rb +8 -0
  76. data/test/core_test_app/app/components/self_reloading.rb +25 -0
  77. data/test/core_test_app/app/components/server_counter/javascripts/server_counter.js +4 -4
  78. data/test/core_test_app/app/components/server_counter.rb +10 -10
  79. data/test/core_test_app/app/components/simple_authentication_component.rb +1 -0
  80. data/test/core_test_app/app/components/simple_component.rb +0 -4
  81. data/test/core_test_app/app/components/simple_composite.rb +1 -1
  82. data/test/core_test_app/app/components/simple_form_with_file_upload.rb +1 -2
  83. data/test/core_test_app/app/components/simple_tab_panel.rb +5 -3
  84. data/test/core_test_app/app/components/{panel_with_tools.rb → tools.rb} +3 -3
  85. data/test/core_test_app/app/components/window_with_simple_component.rb +1 -0
  86. data/test/core_test_app/app/controllers/alternative_controller.rb +10 -0
  87. data/test/core_test_app/app/controllers/specs_controller.rb +11 -0
  88. data/test/core_test_app/app/views/layouts/application.html.erb +19 -1
  89. data/test/core_test_app/app/views/simple_rails/multiple_nested.html.erb +2 -2
  90. data/test/core_test_app/config/boot.rb +3 -10
  91. data/test/core_test_app/config/environments/development.rb +1 -0
  92. data/test/core_test_app/config/initializers/netzke.rb +4 -1
  93. data/test/core_test_app/config/locales/en.yml +11 -4
  94. data/test/core_test_app/config/locales/es.yml +1 -4
  95. data/test/core_test_app/config/routes.rb +10 -1
  96. data/test/core_test_app/core_test_app.tmproj +254 -0
  97. data/test/core_test_app/db/development.sqlite3 +0 -0
  98. data/test/core_test_app/{lib/tasks/.gitkeep → db/test.sqlite3} +0 -0
  99. data/test/core_test_app/log/development.log +78046 -0
  100. data/test/core_test_app/log/production.log +18 -0
  101. data/test/core_test_app/log/test.log +120048 -0
  102. data/test/core_test_app/rails_app.tmproj +324 -0
  103. data/test/core_test_app/tmp/cache/assets/C8B/BF0/sprockets%2F54de2792b036d1dab855f88599503551 +0 -0
  104. data/test/core_test_app/tmp/cache/assets/C92/5A0/sprockets%2F39e75754782ee12179bf35c9a0971d80 +0 -0
  105. data/test/core_test_app/tmp/cache/assets/C99/720/sprockets%2F981d5a1b957a012e380b22011a6d176d +0 -0
  106. data/test/core_test_app/tmp/cache/assets/C9F/750/sprockets%2F20ce3d64040a5d3a0a8883bd60754356 +0 -0
  107. data/test/core_test_app/tmp/cache/assets/CC4/C00/sprockets%2Fc615df52887d8c2e67e8413576a419c5 +0 -0
  108. data/test/core_test_app/tmp/cache/assets/CF1/3F0/sprockets%2Fc69ee42924fab565a3533d56473ce878 +0 -0
  109. data/test/core_test_app/tmp/cache/assets/D0E/870/sprockets%2Fa593bf4fac106add88c9434141a49663 +0 -0
  110. data/test/core_test_app/tmp/cache/assets/D14/8E0/sprockets%2F20748e8d1d7d090d122904a9fe6f18fc +0 -0
  111. data/test/core_test_app/tmp/cache/assets/D3E/DA0/sprockets%2Fa175f1ac5996544b908ba3ba3f64c4f3 +0 -0
  112. data/test/core_test_app/tmp/cache/assets/D43/C00/sprockets%2F7bc60c758776356d615ab5edff201ee2 +0 -0
  113. data/test/core_test_app/tmp/cache/assets/D4B/C50/sprockets%2F8483b7e322da338e8f9eb3b30a957e9a +0 -0
  114. data/test/core_test_app/tmp/cache/assets/D64/090/sprockets%2F5a01ff309c3f2503eb5e4f5667cca4b3 +0 -0
  115. data/test/core_test_app/tmp/cache/assets/D8B/FB0/sprockets%2F7a86225caaa389f1be600b4f3a2d1ef0 +0 -0
  116. data/test/core_test_app/tmp/cache/assets/D98/9C0/sprockets%2F18b80e8fe200aebc522e561a867ea6fb +0 -0
  117. data/test/core_test_app/tmp/cache/assets/DB0/6E0/sprockets%2F03e33f5a4779eeb48bcfc86ee717fb55 +0 -0
  118. data/test/core_test_app/tmp/cache/assets/DED/7E0/sprockets%2Feaedd52ba538f19e4ab543a3e20ce2c4 +0 -0
  119. data/test/core_test_app/tmp/cache/assets/E07/FF0/sprockets%2Fb3c071e0a6de36f041adbbdaa8ab060b +0 -0
  120. data/test/core_test_app/tmp/capybara/capybara-20101214105940.html +40 -0
  121. data/test/core_test_app/tmp/capybara/capybara-20101214110642.html +40 -0
  122. data/test/core_test_app/tmp/capybara/capybara-20101214110749.html +40 -0
  123. data/test/core_test_app/tmp/capybara/capybara-20101214110750.html +40 -0
  124. data/test/core_test_app/tmp/capybara/capybara-20101214111025.html +40 -0
  125. data/test/core_test_app/tmp/capybara/capybara-20101214111027.html +40 -0
  126. data/test/core_test_app/tmp/capybara/capybara-20101214111213.html +40 -0
  127. data/test/core_test_app/tmp/capybara/capybara-20101214111214.html +40 -0
  128. data/test/core_test_app/tmp/capybara/capybara-20101214111332.html +40 -0
  129. data/test/core_test_app/tmp/capybara/capybara-20101214111333.html +40 -0
  130. data/test/core_test_app/{spec/component → tmp/pids/passenger.3000.pid.lock} +0 -0
  131. metadata +370 -133
  132. data/.autotest +0 -1
  133. data/.travis.yml +0 -18
  134. data/Manifest +0 -50
  135. data/config/ci/before-travis.sh +0 -10
  136. data/install.rb +0 -1
  137. data/lib/netzke/core/options_hash.rb +0 -27
  138. data/lib/netzke/core/ruby_ext/string.rb +0 -26
  139. data/lib/netzke/core/ruby_ext/symbol.rb +0 -13
  140. data/netzke-core.gemspec +0 -253
  141. data/test/core_test_app/.gitignore +0 -4
  142. data/test/core_test_app/.powrc +0 -4
  143. data/test/core_test_app/.rvmrc +0 -1
  144. data/test/core_test_app/Gemfile +0 -19
  145. data/test/core_test_app/Gemfile.lock +0 -147
  146. data/test/core_test_app/app/components/border_layout_panel.rb +0 -4
  147. data/test/core_test_app/app/components/card_component_loader.rb +0 -25
  148. data/test/core_test_app/app/components/component_with_custom_css.rb +0 -11
  149. data/test/core_test_app/app/components/component_with_js_mixin/javascripts/component_with_js_mixin.js +0 -5
  150. data/test/core_test_app/app/components/component_with_js_mixin/javascripts/extra_one.js +0 -2
  151. data/test/core_test_app/app/components/component_with_js_mixin/javascripts/extra_two.js +0 -2
  152. data/test/core_test_app/app/components/component_with_nested_through.rb +0 -28
  153. data/test/core_test_app/app/components/component_with_required_js.rb +0 -24
  154. data/test/core_test_app/app/components/dsl_delegated_properties.rb +0 -4
  155. data/test/core_test_app/app/components/dsl_delegated_properties_base.rb +0 -5
  156. data/test/core_test_app/app/components/extended_component_with_actions.rb +0 -9
  157. data/test/core_test_app/app/components/extended_component_with_js_mixin/javascripts/some_method_set.js +0 -5
  158. data/test/core_test_app/app/components/extended_component_with_js_mixin.rb +0 -10
  159. data/test/core_test_app/app/components/extended_localized_panel.rb +0 -2
  160. data/test/core_test_app/app/components/included.js +0 -5
  161. data/test/core_test_app/app/components/inline_composite.rb +0 -13
  162. data/test/core_test_app/app/components/loader_of_component_with_custom_css.rb +0 -23
  163. data/test/core_test_app/app/components/multipane_component_loader.rb +0 -41
  164. data/test/core_test_app/app/components/nested_component.rb +0 -17
  165. data/test/core_test_app/app/components/panel_with_plugin.rb +0 -9
  166. data/test/core_test_app/app/components/scoped_components/deep_scoped_components/some_deep_scoped_component.rb +0 -10
  167. data/test/core_test_app/app/components/scoped_components/extended_scoped_component.rb +0 -8
  168. data/test/core_test_app/app/components/scoped_components/some_scoped_component.rb +0 -8
  169. data/test/core_test_app/app/components/some_ext_component.rb +0 -8
  170. data/test/core_test_app/app/components/some_plugin.rb +0 -40
  171. data/test/core_test_app/app/components/stateful_component.rb +0 -46
  172. data/test/core_test_app/app/components/stateful_component_with_shared_state.rb +0 -11
  173. data/test/core_test_app/config/database.yml.travis +0 -11
  174. data/test/core_test_app/db/schema.rb +0 -29
  175. data/test/core_test_app/features/actions_and_tools.feature +0 -22
  176. data/test/core_test_app/features/basic.feature +0 -7
  177. data/test/core_test_app/features/client-server.feature +0 -19
  178. data/test/core_test_app/features/complex_component.feature +0 -18
  179. data/test/core_test_app/features/component.feature +0 -10
  180. data/test/core_test_app/features/component_loader.feature +0 -52
  181. data/test/core_test_app/features/composition.feature +0 -45
  182. data/test/core_test_app/features/config_to_dsl_delegation.feature +0 -10
  183. data/test/core_test_app/features/custom_css.feature +0 -17
  184. data/test/core_test_app/features/ext.direct.feature +0 -32
  185. data/test/core_test_app/features/file_inclusion.feature +0 -10
  186. data/test/core_test_app/features/i18n.feature +0 -35
  187. data/test/core_test_app/features/inheritance.feature +0 -18
  188. data/test/core_test_app/features/js_include.feature +0 -20
  189. data/test/core_test_app/features/nested_views.feature +0 -10
  190. data/test/core_test_app/features/persistence.feature +0 -34
  191. data/test/core_test_app/features/plugin.feature +0 -16
  192. data/test/core_test_app/features/rails_views.feature +0 -16
  193. data/test/core_test_app/features/scopes.feature +0 -14
  194. data/test/core_test_app/features/step_definitions/custom_css_steps.rb +0 -7
  195. data/test/core_test_app/features/step_definitions/generic_steps.rb +0 -64
  196. data/test/core_test_app/features/step_definitions/web_steps.rb +0 -219
  197. data/test/core_test_app/features/support/env.rb +0 -58
  198. data/test/core_test_app/features/support/paths.rb +0 -42
  199. data/test/core_test_app/spec/action_config_spec.rb +0 -15
  200. data/test/core_test_app/spec/actions_spec.rb +0 -96
  201. data/test/core_test_app/spec/base_spec.rb +0 -35
  202. data/test/core_test_app/spec/client_class_spec.rb +0 -17
  203. data/test/core_test_app/spec/composition_spec.rb +0 -118
  204. data/test/core_test_app/spec/core_ext_spec.rb +0 -27
  205. data/test/core_test_app/spec/endpoint_response_spec.rb +0 -17
  206. data/test/core_test_app/spec/javascript_spec.rb +0 -33
  207. data/test/core_test_app/spec/js_class_config_scope.rb +0 -37
  208. data/test/core_test_app/spec/panel_spec.rb +0 -11
  209. data/test/core_test_app/spec/services_spec.rb +0 -16
  210. data/test/core_test_app/spec/spec.opt +0 -2
  211. data/test/core_test_app/spec/spec_helper.rb +0 -27
  212. data/test/core_test_app/spec/state_spec.rb +0 -20
  213. data/test/core_test_app/vendor/plugins/.gitkeep +0 -0
  214. data/test/unit/core_ext_test.rb +0 -8
  215. data/test/unit/netzke_core_test.rb +0 -178
  216. data/uninstall.rb +0 -1
data/CHANGELOG.md CHANGED
@@ -1,6 +1,21 @@
1
+ # v0.8.2 - 2013-03-12
2
+ * bug fix
3
+ * RuntimeError "can't add a new key into hash during iteration" in Composition in some scenarious (thanks @wupdiwup)
4
+ * netzkeReload works again
5
+
6
+ * improvements
7
+ * minimize core Ruby class extensions
8
+ * tests can now be run by simply executing `rake` from the gem's root (thanks @allomov)
9
+ * feedback delay is now globally configurable
10
+ * netzkeFeedback now understands {delay: seconds} as second parameter
11
+ * add support for arbitrary controllers replacing NetzkeController
12
+ * add support for HAML templates
13
+ * some code refactoring
14
+ * tests are rewritten with Mocha.js and CoffeeScript
15
+
1
16
  # v0.8.1 - 2012-12-15
2
17
  * bug fix
3
- * in production, JS comment stripping could cause modification of form_authenticity_token (issue #43) - by @scho
18
+ * in production, JS comment stripping could cause modification of form_authenticity_token (issue #43) (thanks @scho)
4
19
 
5
20
  # v0.8.0 - 2012-12-09
6
21
  ## Misc
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'haml'
6
+
7
+ group :test do
8
+ gem 'capybara'
9
+ gem 'database_cleaner'
10
+ gem 'rspec-rails'
11
+ gem 'pry-rails'
12
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Netzke Core [![Build Status](https://secure.travis-ci.org/nomadcoder/netzke-core.png?branch=master)](http://travis-ci.org/nomadcoder/netzke-core) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/netzke/netzke-core)
1
+ # Netzke Core [![Gem Version](https://fury-badge.herokuapp.com/rb/netzke-core.png)](http://badge.fury.io/rb/netzke-core) [![Build Status](https://travis-ci.org/netzke/netzke-core.png?branch=master)](https://travis-ci.org/netzke/netzke-core) [![Code Climate](https://codeclimate.com/github/netzke/netzke-core.png)](https://codeclimate.com/github/netzke/netzke-core)
2
2
 
3
3
  [RDocs](http://rdoc.info/projects/netzke/netzke-core)
4
4
 
@@ -31,6 +31,8 @@ All this extremely facilitates building fast, low-traffic, robust, and highly ma
31
31
 
32
32
  *This component is distributed as a part of the test application, see `test/core_test_app/components`.*
33
33
 
34
+ Ext JS files are not distributed with Netzke, so, make sure that they are located in (or sym-linked as) `YOUR_APP/public/extjs`.
35
+
34
36
  In `YOUR_APP/components/hello_world.rb`:
35
37
 
36
38
  ```ruby
@@ -248,7 +250,7 @@ Actions can also be referred to is submenus:
248
250
  c.tbar = [{text: 'Menu', menu: {items: [:show_report]}}]
249
251
  ```
250
252
 
251
- For more details on composition refer to [Netzke::Core::Action](http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Action).
253
+ For more details on composition refer to [Netzke::Core::Actions](http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Actions).
252
254
 
253
255
  ## Client-server interaction
254
256
 
@@ -285,7 +287,7 @@ An endpoint can instruct the client class to execute a set of methods after its
285
287
  ```ruby
286
288
  class SimpleComponent < Netzke::Base
287
289
  endpoint :whats_up_server do |params, this|
288
- this.set_title("All quiet here on the server")
290
+ this.set_title("Response from server")
289
291
  this.my_method
290
292
  end
291
293
  end
@@ -317,6 +319,10 @@ Netzke Core will automatically include Ext JS localization files based on curren
317
319
 
318
320
  Also, Netzke Core uses some conventions for localizing actions. Refer to [Netzke::Core::Actions](http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Actions).
319
321
 
322
+ ## HAML support (experimental)
323
+
324
+ Netzke provides support for HAML templates in case you don't want to put HTML into Ruby files.
325
+
320
326
  ## Requirements
321
327
 
322
328
  * Ruby ~> 1.9.2
@@ -325,41 +331,42 @@ Also, Netzke Core uses some conventions for localizing actions. Refer to [Netzke
325
331
 
326
332
  ## Installation
327
333
 
328
- $ gem install netzke-core
334
+ $ gem install netzke-core
329
335
 
330
336
  For the latest ("edge") stuff, instruct the bundler to get the gem straight from github:
331
337
 
332
338
  ```ruby
333
- gem 'netzke-core', git: "git://github.com/netzke/netzke-core.git"
339
+ gem 'netzke-core', github: "netzke/netzke-core"
334
340
  ```
335
341
 
336
- By default, Netzke assumes that your Ext JS library is located in public/extjs. It can be a symbolic link, e.g.:
342
+ By default, Netzke assumes that your Ext JS library is located in `public/extjs`. It can be a symbolic link, e.g.:
337
343
 
338
- $ ln -s ~/code/sencha/ext-4.1.1 public/extjs
344
+ $ ln -s PATH/TO/YOUR/EXTJS/FILES public/extjs
339
345
 
340
346
  *(Make sure that the location of the license.txt distributed with Ext JS is exactly `public/extjs/license.txt`)*
341
347
 
342
348
  ## Running tests
343
349
 
344
- The bundled `test/core_test_app` application used for automated testing can be easily run as a stand-alone Rails app. It's a good source of concise, focused examples. After starting the application, access any of the test components (located in `app/components`) by using the following url:
350
+ The bundled `test/core_test_app` application used for automated testing can be easily run as a stand-alone Rails app. It's a good source of concise, focused examples. After starting the application, access any of the test components (located in `test/core_test_app/app/components`) by using the following url:
345
351
 
346
352
  http://localhost:3000/components/{name of the component's class}
347
353
 
348
- For example [http://localhost:3000/components/ServerCaller](http://localhost:3000/components/ServerCaller)
354
+ For example [http://localhost:3000/components/Endpoints](http://localhost:3000/components/Endpoints)
349
355
 
350
- Before being able run the test app and the tests themselves, you must link your Ext JS library to `test/core_test_app/public`, e.g. (from the gems's root):
356
+ To run a specific Mocha JS spec (located in `spec/mocha`) for a component, append `?spec={name of spec}`, for example:
351
357
 
352
- $ ln -s ~/code/sencha/ext-4.1.1 test/core_test_app/public/extjs
358
+ [http://localhost:3000/components/Endpoints?spec=endpoints](http://localhost:3000/components/Endpoints?spec=endpoints)
353
359
 
354
- For cucumber tests (from `test/core_test_app`):
360
+ To run all the tests (from the gem's root):
355
361
 
356
- $ cucumber features
362
+ $ rake
357
363
 
358
- For RSpec tests (from `test/core_test_app`):
364
+ This assumes that the Ext JS library is located/symlinked in `test/core_test_app/public/extjs`. If you want to use Sencha CDN instead, run:
359
365
 
360
- $ rspec spec
366
+ $ EXTJS_SRC=cdn rake
361
367
 
362
368
  ## Useful links
369
+
363
370
  * [Project website](http://netzke.org)
364
371
  * [Live demo](http://netzke-demo.herokuapp.com) (features [Netzke Basepack](https://github.com/netzke/netzke-basepack), with sample code)
365
372
  * [Twitter](http://twitter.com/netzke) - latest news about the framework
data/Rakefile CHANGED
@@ -1,44 +1,25 @@
1
- begin
2
- require 'jeweler'
3
- require './lib/netzke/core/version'
4
- Jeweler::Tasks.new do |gemspec|
5
- gemspec.version = Netzke::Core::Version::STRING
6
- gemspec.name = "netzke-core"
7
- gemspec.summary = "Client-server GUI components with Sencha Ext JS and Ruby"
8
- gemspec.description = "Allows building complex RIA by greatly facilitating modular development"
9
- gemspec.email = "nmcoder@gmail.com"
10
- gemspec.homepage = "http://netzke.org"
11
- gemspec.authors = ["nomadcoder"]
12
- gemspec.add_dependency("activesupport", ">=3.1.0")
13
- end
14
- Jeweler::GemcutterTasks.new
15
- rescue LoadError
16
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
- end
1
+ require "bundler/gem_tasks"
2
+ require 'yard'
18
3
 
19
- require 'rake/testtask'
20
- Rake::TestTask.new(:test) do |test|
21
- test.libs << 'lib' << 'test'
22
- test.pattern = 'test/**/*_test.rb'
23
- test.verbose = true
24
- end
4
+ # Load tasks, that will be available for Rails user
5
+ Dir[File.join(File.dirname(__FILE__), './lib/tasks/*.rake')].each { |file| load file }
25
6
 
26
- begin
27
- require 'yard'
7
+ # Load tasks for gem development
8
+ Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |file| load file }
28
9
 
29
- YARD::Rake::YardocTask.new do |t|
30
- t.options = ['--title', "Netzke Core #{Netzke::Core::Version::STRING}"]
31
- end
10
+ YARD::Rake::YardocTask.new do |t|
11
+ t.options = ['--title', "Netzke Core #{Netzke::Core::Version::STRING}"]
12
+ end
32
13
 
33
- namespace :yard do
34
- desc "Publish docs to api.netzke.org"
35
- task publish: :yard do
36
- dir = 'www/api.netzke.org/core'
37
- puts "Publishing to fl:#{dir}..."
38
- `ssh fl "mkdir -p #{dir}"`
39
- `scp -r doc/* fl:#{dir}`
40
- end
14
+ namespace :yard do
15
+ desc "Publish docs to api.netzke.org"
16
+ task publish: :yard do
17
+ dir = 'www/api.netzke.org/core'
18
+ puts "Publishing to fl:#{dir}..."
19
+ `ssh fl "mkdir -p #{dir}"`
20
+ `scp -r doc/* fl:#{dir}`
41
21
  end
42
- rescue
43
- puts "To enable yard do 'gem install yard'"
44
22
  end
23
+
24
+ desc 'rake test'
25
+ task default: :test
@@ -1,81 +1,3 @@
1
1
  class NetzkeController < ApplicationController
2
- # Action for Ext.Direct RPC calls
3
- def direct
4
- result=""
5
- error=false
6
- if params['_json'] # this is a batched request
7
- params['_json'].each do |batch|
8
- result += result.blank? ? '[' : ', '
9
- begin
10
- result += invoke_endpoint(batch[:act], batch[:method].underscore, batch[:data].first, batch[:tid])
11
- rescue Exception => e
12
- logger.error "!!! Netzke: Error invoking endpoint: #{batch[:act]} #{batch[:method].underscore} #{batch[:data].inspect} #{batch[:tid]}\n"
13
- logger.error e.message
14
- logger.error e.backtrace.join("\n")
15
- error=true
16
- break;
17
- end
18
- end
19
- result+=']'
20
- else # this is a single request
21
- result=invoke_endpoint params[:act], params[:method].underscore, params[:data].first, params[:tid]
22
- end
23
- render :text => result, :layout => false, :status => error ? 500 : 200
24
- end
25
-
26
- # On-the-fly generation of public/netzke/ext.[js|css]
27
- def ext
28
- respond_to do |format|
29
- format.js {
30
- render :text => Netzke::Core::DynamicAssets.ext_js(form_authenticity_token)
31
- }
32
-
33
- format.css {
34
- render :text => Netzke::Core::DynamicAssets.ext_css
35
- }
36
- end
37
- end
38
-
39
- # Old-way action used at multi-part form submission (endpointUrl)
40
- def dispatcher
41
- endpoint_dispatch(params[:address])
42
- end
43
-
44
- protected
45
-
46
- def invoke_endpoint(endpoint_path, action, params, tid)
47
- component_name, *sub_components = endpoint_path.split('__')
48
- components_in_session = session[:netzke_components]
49
-
50
- if components_in_session
51
- component_instance = Netzke::Base.instance_by_config(components_in_session[component_name.to_sym])
52
- result = component_instance.invoke_endpoint((sub_components + [action]).join("__"), params).to_nifty_json
53
- else
54
- result = {:netzke_component_not_in_session => true}.to_nifty_json
55
- end
56
-
57
- # We render text/plain, so that the browser never modifies our response
58
- response.headers["Content-Type"] = "text/plain; charset=utf-8"
59
-
60
- { :type => "rpc",
61
- :tid => tid,
62
- :action => component_name,
63
- :method => action,
64
- :result => result.present? && result.l || {}
65
- }.to_json
66
- end
67
-
68
- # The dispatcher for the old-style requests (used for multi-part form submission). The URL contains the name of the component,
69
- # as well as the method of this component to be called, according to the double underscore notation.
70
- # E.g.: some_grid__post_grid_data.
71
- def endpoint_dispatch(endpoint_path)
72
- component_name, *sub_components = endpoint_path.split('__')
73
- component_instance = Netzke::Base.instance_by_config(session[:netzke_components][component_name.to_sym])
74
-
75
- # We can't do this here; this method is only used for classic form submission, and the response from the server should be the (default) "text/html"
76
- # response.headers["Content-Type"] = "text/plain; charset=utf-8"
77
-
78
- render :text => component_instance.invoke_endpoint(sub_components.join("__"), params).to_nifty_json, :layout => false
79
- end
80
-
2
+ include Netzke::Railz::ControllerExtensions
81
3
  end
data/javascripts/ext.js CHANGED
@@ -22,25 +22,26 @@ Ext.QuickTips.init();
22
22
 
23
23
  // FeedbackGhost is a little class that displays unified feedback from Netzke components.
24
24
  Ext.define('Netzke.FeedbackGhost', {
25
- showFeedback: function(msg){
26
- if (!msg) Netzke.exception("Netzke.FeedbackGhost#showFeedback: wrong number of arguments (0 for 1)");
25
+ showFeedback: function(msg, options){
26
+ options = options || {};
27
+ options.delay = options.delay || Netzke.core.FeedbackDelay;
27
28
  if (Ext.isObject(msg)) {
28
- this.msg(msg.level.camelize(), msg.msg);
29
+ this.msg(msg.level.camelize(), msg.msg, options.delay);
29
30
  } else if (Ext.isArray(msg)) {
30
31
  Ext.each(msg, function(m) { this.showFeedback(m); }, this);
31
32
  } else {
32
- this.msg(null, msg); // no header for now
33
+ this.msg(null, msg, options.delay); // no header for now
33
34
  }
34
35
  },
35
36
 
36
- msg: function(title, format){
37
+ msg: function(title, format, delay){
37
38
  if(!this.msgCt){
38
39
  this.msgCt = Ext.core.DomHelper.insertFirst(document.body, {id:'msg-div'}, true);
39
40
  }
40
41
  var s = Ext.String.format.apply(String, Array.prototype.slice.call(arguments, 1));
41
42
  var m = Ext.core.DomHelper.append(this.msgCt, this.createBox(title, s), true);
42
43
  m.hide();
43
- m.slideIn('t').ghost("t", { delay: 1000, remove: true});
44
+ m.slideIn('t').ghost("t", { delay: delay, remove: true});
44
45
  },
45
46
 
46
47
  createBox: function(t, s){
@@ -356,12 +357,15 @@ Ext.define(null, {
356
357
  },
357
358
 
358
359
  /**
359
- * Reloads current component (calls the parent to reload us as its component)
360
+ * Reloads itself by instructing the parent to call `netzkeLoadComponent`.
361
+ * Note: in order for this to work, the component must be nested in a container with the 'fit' layout.
360
362
  */
361
363
  netzkeReload: function(){
362
364
  var parent = this.netzkeGetParentComponent();
365
+
363
366
  if (parent) {
364
- parent.netzkeLoadComponent({id:this.netzkeLocalId(parent), container:this.ownerCt.id});
367
+ var name = this.netzkeLocalId(parent);
368
+ parent.netzkeLoadComponent(name, {container:this.ownerCt.id});
365
369
  } else {
366
370
  window.location.reload();
367
371
  }
@@ -396,13 +400,13 @@ Ext.define(null, {
396
400
  /**
397
401
  * Provides a visual feedback. TODO: refactor
398
402
  */
399
- netzkeFeedback: function(msg){
400
- if (this.initialConfig && this.initialConfig.quiet) {
401
- return false;
402
- }
403
+ netzkeFeedback: function(msg, options){
404
+ if (this.initialConfig && this.initialConfig.quiet) return false;
405
+
406
+ options = options || {};
403
407
 
404
408
  if (this.feedbackGhost) {
405
- this.feedbackGhost.showFeedback(msg);
409
+ this.feedbackGhost.showFeedback(msg, {delay: options.delay});
406
410
  } else {
407
411
  // there's no application to show the feedback - so, we do it ourselves
408
412
  if (typeof msg == 'string'){
data/lib/netzke/base.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'active_support/core_ext'
2
2
  require 'netzke/core/ruby_ext'
3
+ require 'netzke/core/dsl_support'
3
4
  require 'netzke/core/javascript'
4
5
  require 'netzke/core/stylesheets'
5
6
  require 'netzke/core/services'
@@ -10,6 +11,7 @@ require 'netzke/core/state'
10
11
  require 'netzke/core/embedding'
11
12
  require 'netzke/core/actions'
12
13
  require 'netzke/core/session'
14
+ require 'netzke/core/html' if Module.const_defined?(:Haml)
13
15
 
14
16
  module Netzke
15
17
  # The base class for every Netzke component. Its main responsibilities include:
@@ -43,6 +45,7 @@ module Netzke
43
45
  #
44
46
  # This doesn't necessarily have to be used in toolbars, but also in other places in config (i.e. layouts).
45
47
  class Base
48
+ include Core::DslSupport
46
49
  include Core::Session
47
50
  include Core::State
48
51
  include Core::Configuration
@@ -53,7 +56,9 @@ module Netzke
53
56
  include Core::Stylesheets
54
57
  include Core::Embedding
55
58
  include Core::Actions
59
+ include Core::Html if const_defined? :Haml
56
60
 
61
+ # DELETE ME
57
62
  class_attribute :default_instance_config
58
63
  self.default_instance_config = {}
59
64
 
@@ -104,8 +109,7 @@ module Netzke
104
109
 
105
110
  # Instantiates a component instance. A parent can optionally be provided.
106
111
  def initialize(conf = {}, parent = nil)
107
- @passed_config = conf # configuration passed at the moment of instantiation
108
- @passed_config.deep_freeze
112
+ @passed_config = conf.deep_dup # configuration passed at the moment of instantiation
109
113
  @parent = parent
110
114
  @name = conf[:name] || self.class.name.underscore
111
115
  @js_id = parent.nil? ? @name : "#{parent.js_id}__#{@name}"
@@ -4,6 +4,8 @@ module Netzke::Core
4
4
  # class MyComponent < Netzke::Base
5
5
  # action :do_something do |c|
6
6
  # c.text = "Do it!"
7
+ # c.tooltip = "Do something"
8
+ # c.icon = :tick
7
9
  # end
8
10
  # end
9
11
  class ActionConfig < ActiveSupport::OrderedOptions
@@ -14,6 +16,7 @@ module Netzke::Core
14
16
 
15
17
  build_localized_attributes
16
18
 
19
+ self.name = @name
17
20
  self.text = @text.presence || @name.humanize
18
21
  self.tooltip = @tooltip.presence || @name.humanize
19
22
  self.icon = @icon.to_sym if @icon.present?
@@ -23,6 +26,10 @@ module Netzke::Core
23
26
  self[:icon] = path.is_a?(Symbol) ? Netzke::Base.uri_to_icon(path) : path
24
27
  end
25
28
 
29
+ # later
30
+ def set_defaults!
31
+ end
32
+
26
33
  private
27
34
 
28
35
  def build_localized_attributes
@@ -67,29 +67,12 @@ module Netzke::Core
67
67
  module Actions
68
68
  extend ActiveSupport::Concern
69
69
 
70
- ACTION_METHOD_NAME = "%s_action"
71
-
72
70
  included do
73
- # Returns registered actions
74
- class_attribute :registered_actions
75
- self.registered_actions = []
71
+ # Declares Base.action, for declaring actions, and Base#actions, which returns a [Hash] of all action configs by name
72
+ declare_dsl_for :actions
76
73
  end
77
74
 
78
75
  module ClassMethods
79
- def action(name, &block)
80
- self.registered_actions |= [name]
81
-
82
- method_name = ACTION_METHOD_NAME % name
83
-
84
- if block_given?
85
- define_method(method_name, &block)
86
- else
87
- define_method(method_name) do |action_config|
88
- action_config
89
- end
90
- end
91
- end
92
-
93
76
  # Must stay public, used from ActionConfig
94
77
  # @return [String|nil] full URI to an icon file by its name (provided we have a controller)
95
78
  def uri_to_icon(icon)
@@ -97,24 +80,15 @@ module Netzke::Core
97
80
  end
98
81
  end
99
82
 
100
- # All actions for this instance
101
- def actions
102
- @actions ||= self.class.registered_actions.inject({}) do |res, name|
103
- action_config = Netzke::Core::ActionConfig.new(name, self)
104
- send(ACTION_METHOD_NAME % name, action_config)
105
- if action_config.excluded
106
- res.merge(name.to_sym => {excluded: true})
107
- else
108
- res.merge(name.to_sym => action_config)
109
- end
110
- end
111
- end
112
-
113
83
  def js_configure(c)
114
84
  super
115
85
  c.actions = actions
116
86
  end
117
87
 
88
+ def extend_item(item)
89
+ super detect_and_normalize(:action, item)
90
+ end
91
+
118
92
  private
119
93
  def uri_to_icon(icon)
120
94
  self.class.uri_to_icon(icon)
@@ -235,7 +235,7 @@ Netzke.cache.push('#{xtype}');
235
235
  end
236
236
 
237
237
  def properties_as_string
238
- [properties.to_nifty_json.chop, mixins_as_string].compact.join(",\n") + "}"
238
+ [properties.netzke_jsonify.to_json.chop, mixins_as_string].compact.join(",\n") + "}"
239
239
  end
240
240
 
241
241
  # Default extended class
@@ -1,6 +1,6 @@
1
1
  module Netzke::Core
2
2
  class ComponentConfig < ActiveSupport::OrderedOptions
3
- def initialize(name)
3
+ def initialize(name, parent)
4
4
  self.name = name.to_s
5
5
  end
6
6
 
@@ -79,16 +79,10 @@ module Netzke::Core
79
79
  module Composition
80
80
  extend ActiveSupport::Concern
81
81
 
82
- COMPONENT_METHOD_NAME = "%s_component"
83
-
84
-
85
82
  included do
83
+ # Declares Base.component, for declaring child componets, and Base#components, which returns a [Hash] of all component configs by name
84
+ declare_dsl_for :components
86
85
 
87
- # Returns registered components
88
- class_attribute :registered_components
89
- self.registered_components = []
90
-
91
- # @!method Foobar
92
86
  # Loads a component on browser's request. Every Netzke component gets this endpoint.
93
87
  # <tt>params</tt> should contain:
94
88
  # * <tt>:cache</tt> - an array of component classes cached at the browser
@@ -112,44 +106,6 @@ module Netzke::Core
112
106
 
113
107
  end # included
114
108
 
115
- module ClassMethods
116
-
117
- # Declares a child (nested) component.
118
- # @param name [Symbol] component name
119
- # @param block [Proc] config block
120
- # @example
121
- # component :users do |c|
122
- # c.klass = Netzke::Basepack::Grid
123
- # c.modul = "User"
124
- # end
125
- def component(name, &block)
126
- self.registered_components |= [name]
127
-
128
- method_name = COMPONENT_METHOD_NAME % name
129
- if block_given?
130
- define_method(method_name, &block)
131
- else
132
- define_method(method_name) do |component_config|
133
- component_config
134
- end
135
- end
136
- end
137
- end
138
-
139
- # @return [Hash] component configs by name
140
- def components
141
- @components ||= self.class.registered_components.inject({}) do |out, name|
142
- component_config = Netzke::Core::ComponentConfig.new(name)
143
- send(COMPONENT_METHOD_NAME % name, component_config)
144
- component_config.set_defaults!
145
- if component_config.excluded
146
- out.merge(name.to_sym => {excluded: true})
147
- else
148
- out.merge(name.to_sym => component_config)
149
- end
150
- end
151
- end
152
-
153
109
  # @return [Hash] configs of eagerly loaded components by name
154
110
  def eagerly_loaded_components
155
111
  @eagerly_loaded_components ||= components.select{|k,v| components_in_config.include?(k) || v[:eager_loading]}
@@ -163,30 +119,18 @@ module Netzke::Core
163
119
  # Called when the method_missing tries to processes a non-existing component. Override when needed.
164
120
  def component_missing(aggr)
165
121
  flash :error => "Unknown component #{aggr} for #{name}"
166
- {:feedback => @flash}.to_nifty_json
122
+ {:feedback => @flash}.netzke_jsonify.to_json
167
123
  end
168
124
 
169
125
  # Recursively instantiates a child component based on its "path": e.g. if we have component :component1 which in its turn has component :component2, the path to the latter would be "component1__component2"
170
126
  # @param name [Symbol] component name
171
127
  def component_instance(name)
172
- raise ArgumentError, "No component '#{name.inspect}' defined for '#{self.js_id}'" if !name.present?
173
-
174
- @component_instance_cache ||= {}
175
- @component_instance_cache[name] ||= begin
176
- composite = self
177
- name.to_s.split('__').each do |cmp|
178
- cmp = cmp.to_sym
179
-
180
- component_config = composite.components[cmp]
181
- raise ArgumentError, "No component '#{cmp}' defined for '#{composite.js_id}'" if component_config.nil? || component_config[:excluded]
182
-
183
- klass = component_config[:klass]
184
-
185
- instance_config = component_config.merge(:name => cmp)
186
-
187
- composite = klass.new(instance_config, composite) # params: config, parent
188
- end
189
- composite
128
+ @_component_instance ||= {} # memoization
129
+ @_component_instance[name] ||= name.to_s.split('__').inject(self) do |out, cmp_name|
130
+ cmp_config = out.components[cmp_name.to_sym]
131
+ raise ArgumentError, "No component '#{cmp_name}' defined for '#{out.js_id}'" if cmp_config.nil? || cmp_config[:excluded]
132
+ cmp_config[:name] = cmp_name
133
+ cmp_config[:klass].new(cmp_config, out)
190
134
  end
191
135
  end
192
136
 
@@ -218,57 +162,19 @@ module Netzke::Core
218
162
  end
219
163
  end
220
164
 
221
- protected
222
-
223
- # During normalization of the config object, this method is being called with each item found (recursively) in there.
224
- # For example, symbols representing nested child components get replaced with a proper config hash. Same goes for actions.
225
- # Override to do any additional checks/enhancements. See, for example, +Netzke::Basepack::WrapLazyLoaded+.
226
- # @return [Object] extended item
227
165
  def extend_item(item)
228
- # in a situation of action and component being equally named, action will take precedence
229
-
230
- if item.is_a?(Symbol) && item_config = actions[item]
231
- item = {netzke_action: item}
232
- elsif item.is_a?(Symbol) && item_config = components[item]
233
- item = {netzke_component: item}
234
- end
235
-
236
- item[:excluded] = true if item_config && item_config[:excluded]
237
-
238
- if item.is_a?(Hash)
239
- return nil if item[:excluded] # it'll get compacted away by Array#deep_map
240
-
241
- # replace the `component` and `action` keys with `netzke_component` and `netzke_action`, which will be looked for at the JS side
242
- item[:netzke_action] = item.delete(:action) if item[:action]
243
- item[:netzke_component] = item.delete(:component) if item[:component]
244
-
245
- @components_in_config << item[:netzke_component] if item[:netzke_component] && item[:eager_loading] != false
246
- end
247
-
248
- item
166
+ item = detect_and_normalize(:component, item)
167
+ @components_in_config << item[:netzke_component] if include_component?(item)
168
+ super item
249
169
  end
250
170
 
251
171
  private
252
172
 
253
- # We'll build a couple of useful instance variables here:
254
- #
255
- # +components_in_config+ - an array of components (by name) referred in items
256
- # +normalized_config+ - a config that has all the config extensions applied
257
- def normalize_config
258
- @components_in_config = []
259
- @normalized_config = config.dup.tap do |c|
260
- c.each_pair do |k,v|
261
- c.delete(k) if self.class.server_side_config_options.include?(k.to_sym)
262
- c[k] = v.deep_map{|el| extend_item(el)} if v.is_a?(Array)
263
- end
264
- end
265
- end
266
-
267
- # @return [Hash] config with all placeholders (like child components referred by symbols) expanded
268
- def normalized_config
269
- # make sure we call normalize_config first
270
- @normalized_config || (normalize_config || true) && @normalized_config
173
+ def include_component?(cmp_config)
174
+ cmp_config.is_a?(Hash) &&
175
+ cmp_config[:netzke_component] &&
176
+ cmp_config[:eager_loading] != false &&
177
+ !cmp_config[:excluded]
271
178
  end
272
-
273
179
  end
274
180
  end