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
@@ -33,13 +33,6 @@ module Netzke::Core
33
33
 
34
34
  class_attribute :delegated_defaults
35
35
  self.delegated_defaults = {}
36
-
37
- delegated_options.each do |property|
38
- inherited_class.class.send(:define_method, property, lambda { |value|
39
- self.delegated_defaults = self.delegated_defaults.dup if self.superclass.respond_to?(:delegated_defaults) && self.delegated_defaults == self.superclass.delegated_defaults
40
- self.delegated_defaults[property.to_sym] = value
41
- })
42
- end
43
36
  end
44
37
 
45
38
  def configure(c)
@@ -59,5 +59,53 @@ module Netzke::Core
59
59
  def config
60
60
  @config ||= ActiveSupport::OrderedOptions.new
61
61
  end
62
+
63
+
64
+ protected
65
+
66
+ # During the normalization of config object, +extend_item+ is being called with each item found (recursively) in there.
67
+ # For example, symbols representing nested child components get replaced with a proper config hash, same goes for actions (see +Composition+ and +Actions+ respectively).
68
+ # Override to do any additional checks/enhancements. See, for example, +Netzke::Basepack::WrapLazyLoaded+ or +Netzke::Basepack::Fields+.
69
+ # @return [Object|nil] normalized item or nil. If nil is returned, this item will be excluded from the config.
70
+ def extend_item(item)
71
+ item.is_a?(Hash) && item[:excluded] ? nil : item
72
+ end
73
+
74
+ # Used for detecting actions and components referred by symbols. For example, say, action +do_something+ is declared. Then:
75
+ #
76
+ # item #=> :do_something
77
+ # item = detect_and_normalize :action, item
78
+ # item #=> {netzke_action: :do_something, text: 'Do it'} # uses action declaration
79
+ def detect_and_normalize(thing, item)
80
+ if item.is_a?(Symbol) && thing_config = send(thing.to_s.pluralize)[item]
81
+ item = {:"netzke_#{thing}" => item, excluded: thing_config[:excluded]}
82
+ elsif item.is_a?(Hash)
83
+ # replace `action` key with `netzke_action`, which will be looked for at the JS side
84
+ item[:"netzke_#{thing}"] = item.delete(thing) if item[thing]
85
+ end
86
+ item
87
+ end
88
+
89
+ # We'll build a couple of useful instance variables here:
90
+ #
91
+ # +components_in_config+ - an array of components (by name) referred in items
92
+ # +normalized_config+ - a config that has all the config extensions applied
93
+ def normalize_config
94
+ @components_in_config = []
95
+ c = config.dup
96
+ config.each_pair do |k, v|
97
+ c.delete(k) if self.class.server_side_config_options.include?(k.to_sym)
98
+ if v.is_a?(Array)
99
+ c[k] = v.netzke_deep_map{|el| extend_item(el)}
100
+ end
101
+ end
102
+ @normalized_config = c
103
+ end
104
+
105
+ # @return [Hash] config with all placeholders (like child components referred by symbols) expanded
106
+ def normalized_config
107
+ # make sure we call normalize_config first
108
+ @normalized_config || (normalize_config || true) && @normalized_config
109
+ end
62
110
  end
63
111
  end
@@ -0,0 +1,71 @@
1
+ module Netzke
2
+ module Core
3
+ module DslSupport
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ # It's the easiest to be explained by an example:
8
+ #
9
+ # declare_dsl_for :components
10
+ #
11
+ # This creates:
12
+ #
13
+ # 1) DSL method `component` for declaration of child component in a given class, e.g.:
14
+ #
15
+ # component :simple_panel do |c|
16
+ # # ...
17
+ # end
18
+ #
19
+ # Each call to the created `component` method results in an instance method:
20
+ #
21
+ # def simple_panel_component(c)
22
+ # # ...
23
+ # end
24
+ #
25
+ # 2) Instance method `components` that returns a hash of all components configs. This hash is built by passing a new instance of `Netzke::Core::ComponentConfig` to each of the methods described in 1). Presence of `Netzke::Core::ComponentConfig` is assumed.
26
+ #
27
+ # Besides components, this method is being used in Core for DSL for actions.
28
+ def declare_dsl_for(things)
29
+ things = things.to_s
30
+ storage_attribute = :"_declared_#{things}"
31
+
32
+ class_attribute storage_attribute
33
+ send("#{storage_attribute}=", [])
34
+
35
+ define_dsl_method(things, storage_attribute)
36
+ define_collector_method(things, storage_attribute)
37
+ end
38
+
39
+
40
+ def define_dsl_method(things, storage_attribute)
41
+ thing = things.singularize
42
+
43
+ define_singleton_method thing do |name, &block|
44
+ self.send("#{storage_attribute}=", self.send(storage_attribute) | [name])
45
+ method_name = "#{name}_#{thing}"
46
+ define_method(method_name, &(block || ->(c){c}))
47
+ end
48
+ end
49
+
50
+ def define_collector_method(things, storage_attribute)
51
+ thing = things.singularize
52
+ config_class = "Netzke::Core::#{thing.camelcase}Config".constantize
53
+
54
+ define_method things do
55
+ # memoization
56
+ return instance_variable_get("@#{things}") if instance_variable_get("@#{things}")
57
+
58
+ config_hash = self.class.send(storage_attribute).inject({}) do |out, name|
59
+ c = config_class.new(name, self)
60
+ send("#{name}_#{thing}", c)
61
+ c.set_defaults!
62
+ out.merge(name.to_sym => c.excluded ? {excluded: true} : c)
63
+ end
64
+
65
+ instance_variable_set "@#{things}", config_hash
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -16,7 +16,7 @@ module Netzke
16
16
  res << f.read
17
17
  end
18
18
 
19
- defined?(::Rails) && ::Rails.env.production? ? res.strip_js_comments : res
19
+ strip_js_comments(res)
20
20
  end
21
21
 
22
22
  def ext_css
@@ -31,6 +31,14 @@ module Netzke
31
31
  res
32
32
  end
33
33
 
34
+ def strip_js_comments(js_string)
35
+ if defined?(::Rails) && !::Rails.env.development? && compressor = ::Rails.application.assets.js_compressor
36
+ compressor.processor.call(nil, js_string)
37
+ else
38
+ js_string
39
+ end
40
+ end
41
+
34
42
  private
35
43
 
36
44
  # Generates initial javascript code that is dependent on Rails settings
@@ -44,6 +52,7 @@ module Netzke
44
52
  res << %{Netzke.RelativeExtUrl = '#{ActionController::Base.config.relative_url_root}#{Netzke::Core.ext_uri}';}
45
53
 
46
54
  res << %{Netzke.core.directMaxRetries = #{Netzke::Core.js_direct_max_retries};}
55
+ res << %{Netzke.core.FeedbackDelay = #{Netzke::Core.js_feedback_delay};}
47
56
 
48
57
  res.join("\n")
49
58
  end
@@ -3,12 +3,12 @@ module Netzke::Core
3
3
  module Embedding
4
4
  # Instantiating
5
5
  def js_component_instance
6
- %Q{Netzke.page.#{name.jsonify} = Ext.create("#{self.class.js_config.class_alias}", #{js_config.to_nifty_json});}
6
+ %Q{Netzke.page.#{name.to_s.camelize(:lower)} = Ext.create("#{self.class.js_config.class_alias}", #{js_config.netzke_jsonify.to_json});}
7
7
  end
8
8
 
9
9
  # Rendering
10
10
  def js_component_render
11
- %Q{Netzke.page.#{name.jsonify}.render("#{name.to_s.split('_').join('-')}-netzke");} unless self.class.js_config.xtype == "netzkewindow"
11
+ %Q{Netzke.page.#{name.to_s.camelize(:lower)}.render("#{name.to_s.split('_').join('-')}-netzke");} unless self.class.js_config.xtype == "netzkewindow"
12
12
  end
13
13
 
14
14
  # Container for rendering
@@ -0,0 +1,29 @@
1
+ module Netzke
2
+ module Core
3
+ # Provides support for HTML rendering (currently HAML only)
4
+ module Html
5
+ # Will render an HTML template found in +{component_location}/html/+ For example:
6
+ #
7
+ # class MyComponent < Netzke::Base
8
+ # def js_configure(c)
9
+ # super
10
+ # c.html = render(:body)
11
+ # end
12
+ # end
13
+ #
14
+ # This will render the HAML file located in +app/components/my_component/html/body.html.haml
15
+ # The implementation is very simplistic at the moment - e.g. no caching, no support for .erb
16
+ def render(what)
17
+ callr = caller.first
18
+ engine = Haml::Engine.new(File.read(expand_html_path(what, callr)))
19
+ engine.method(:render).call(self)
20
+ end
21
+
22
+ private
23
+
24
+ def expand_html_path(sym, callr = nil)
25
+ %Q(#{callr.split(".rb:").first}/html/#{sym}.html.haml)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -43,35 +43,39 @@ module Netzke::Core
43
43
  def js_configure(c)
44
44
  c.merge!(normalized_config)
45
45
 
46
- # Unique id of the component
47
- c.id = js_id
48
-
49
- # Configuration for all of our non-lazy-loaded children specified here. We can refer to them in +items+ so they get instantiated by Ext.
50
- c.netzke_components = js_components unless js_components.empty?
51
-
52
- # Endpoints (besides the default "deliver_component" - JavaScript side already knows about it)
53
- endpoints = self.class.endpoints.keys - [:deliver_component]
54
-
55
- # pass them as strings, not as symbols
56
- c.endpoints = endpoints.map(&:to_s) unless endpoints.empty?
46
+ # So we can use getComponent(<component_name>) to retrieve a child component
47
+ c.item_id ||= name
57
48
 
58
- # Include our xtype
59
- c.xtype = self.class.js_config.xtype
49
+ %w[id netzke_components endpoints xtype alias i18n netzke_plugins flash].each do |thing|
50
+ js_thing = send "js_#{thing}"
51
+ c[thing] = js_thing if js_thing.present?
52
+ end
60
53
 
61
- # Include our alias: Ext.createByAlias may be used to instantiate the component.
62
- c.alias = self.class.js_config.class_alias
54
+ # reset component session
55
+ # TODO: also remove empty hashes from the global session
56
+ component_session.clear
57
+ end
63
58
 
64
- # So we can use getComponent(<component_name>) to retrieve a child component
65
- c.item_id ||= name
59
+ def js_xtype
60
+ self.class.js_config.xtype
61
+ end
66
62
 
67
- c.i18n = js_translate_properties if js_translate_properties.present?
63
+ # Ext.createByAlias may be used to instantiate the component.
64
+ def js_alias
65
+ self.class.js_config.class_alias
66
+ end
68
67
 
69
- c.netzke_plugins = plugins.map{ |p| p.to_s.camelcase(:lower) } if plugins.present?
68
+ # Endpoints (besides the default "deliver_component" - JavaScript side already knows about it)
69
+ def js_endpoints
70
+ self.class.endpoints.keys - [:deliver_component]
71
+ end
70
72
 
71
- # we need to pass them as strigs, not as symbols
72
- c.tools = c.tools.map(&:to_s) if c.tools.present?
73
+ def js_netzke_plugins
74
+ plugins.map{ |p| p.to_s.camelcase(:lower) }
75
+ end
73
76
 
74
- c.flash = session[:flash] if session && session[:flash].present?
77
+ def js_flash
78
+ session && session[:flash]
75
79
  end
76
80
 
77
81
  # Instance-level client class config. The result of this method (a hash) is converted to a JSON object and passed as options to the constructor of our JavaScript class.
@@ -88,21 +92,23 @@ module Netzke::Core
88
92
  end
89
93
  end
90
94
 
95
+ alias js_netzke_components js_components
96
+
91
97
  # All the JS-code required by this instance of the component to be instantiated in the browser.
92
98
  # It includes JS-classes for the parents, eagerly loaded child components, and itself.
93
99
  def js_missing_code(cached = [])
94
100
  code = dependency_classes.inject("") do |r,k|
95
- cached.include?(k.js_config.xtype) ? r : r + k.js_config.code_with_dependencies.strip_js_comments
101
+ cached.include?(k.js_config.xtype) ? r : r + k.js_config.code_with_dependencies
96
102
  end
97
- code.blank? ? nil : code
103
+ code.blank? ? nil : Netzke::Core::DynamicAssets.strip_js_comments(code)
98
104
  end
99
105
 
100
106
  private
101
107
 
102
108
  # Merges all the translations in the class hierarchy
103
109
  # Note: this method can't be moved out to ClientClass, because I18n is loaded only once, when other Ruby classes are evaluated; so, this must remain at instance level.
104
- def js_translate_properties
105
- @js_translate_properties ||= self.class.netzke_ancestors.inject({}) do |r,klass|
110
+ def js_i18n
111
+ @js_i18n ||= self.class.netzke_ancestors.inject({}) do |r,klass|
106
112
  hsh = klass.js_config.translated_properties.inject({}) { |h,t| h.merge(t => I18n.t("#{klass.i18n_id}.#{t}")) }
107
113
  r.merge(hsh)
108
114
  end
@@ -8,7 +8,7 @@ module Netzke
8
8
 
9
9
  def netzke_ext_css_include(params)
10
10
  # ExtJS base
11
- res = ["#{Netzke::Core.ext_uri}/resources/css/ext-#{params[:theme]}"]
11
+ res = ["#{Netzke::Core.ext_uri}/resources/css/ext-#{params[:theme]}.css"]
12
12
 
13
13
  # Netzke-related dynamic css
14
14
  res << netzke_path(:ext)
@@ -22,7 +22,7 @@ module Netzke
22
22
  res = []
23
23
 
24
24
  # ExtJS
25
- res << (params[:minified] ? "#{Netzke::Core.ext_uri}/ext-all" : "#{Netzke::Core.ext_uri}/ext-all-debug")
25
+ res << (params[:minified] ? "#{Netzke::Core.ext_uri}/ext-all.js" : "#{Netzke::Core.ext_uri}/ext-all-debug.js")
26
26
 
27
27
  # Ext I18n
28
28
  res << "#{Netzke::Core.ext_uri}/locale/ext-lang-#{I18n.locale}" if I18n.locale != :en
@@ -2,16 +2,109 @@ module Netzke
2
2
  module Railz
3
3
  # Before each request, Netzke::Base.controller and Netzke::Base.session are set, to be accessible from components.
4
4
  module ControllerExtensions
5
- def self.included(base)
6
- base.send(:before_filter, :set_controller_and_session)
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ send(:before_filter, :set_controller_and_session)
9
+ end
10
+
11
+ # Handles Ext.Direct RPC calls
12
+ def direct
13
+ if params['_json'] # this is a batched request
14
+ response = []
15
+ params['_json'].each do |batch|
16
+ # response << invoke_endpoint(batch)
17
+ response << direct_response(batch, invoke_endpoint(batch))
18
+ end
19
+ else # this is a single request
20
+ response = direct_response(params, invoke_endpoint(params))
21
+ end
22
+
23
+ render text: response.to_json, layout: false
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 direct_response(request_params, endpoint_response)
47
+ path, action, params, tid = parse_request_params(request_params)
48
+ component_name, *sub_components = path.split('__')
49
+
50
+ # We render text/plain, so that the browser never modifies our response
51
+ response.headers["Content-Type"] = "text/plain; charset=utf-8"
52
+
53
+ { :type => "rpc",
54
+ :tid => tid,
55
+ :action => component_name,
56
+ :method => action,
57
+ :result => ActiveSupport::JSON::Variable.new(endpoint_response.netzke_jsonify.to_json)
58
+ }
7
59
  end
8
60
 
9
- protected
61
+ def invoke_endpoint(request_params)
62
+ path, action, params, tid = parse_request_params(request_params)
63
+
64
+ component_name, *sub_components = path.split('__')
65
+ components_in_session = session[:netzke_components]
66
+
67
+ if components_in_session
68
+ component_instance = Netzke::Base.instance_by_config(components_in_session[component_name.to_sym])
69
+ component_instance.invoke_endpoint((sub_components + [action]).join("__"), params)
70
+ else
71
+ {:netzke_component_not_in_session => true}
72
+ end
73
+ end
74
+
75
+ def parse_request_params(params)
76
+ path = params[:act]
77
+ action = params[:method].underscore
78
+ ep_params = params[:data].try(:first) # Rails >= 3.2.11 returns nil in request_params[:data]
79
+ tid = params[:tid]
80
+
81
+ [path, action, ep_params, tid]
82
+ end
83
+
84
+ # The dispatcher for the old-style requests (used for multi-part form submission). The URL contains the name of the component,
85
+ # as well as the method of this component to be called, according to the double underscore notation.
86
+ # E.g.: some_grid__post_grid_data.
87
+ def endpoint_dispatch(endpoint_path)
88
+ component_name, *sub_components = endpoint_path.split('__')
89
+ component_instance = Netzke::Base.instance_by_config(session[:netzke_components][component_name.to_sym])
90
+
91
+ # 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"
92
+ # response.headers["Content-Type"] = "text/plain; charset=utf-8"
93
+
94
+ render :text => component_instance.invoke_endpoint(sub_components.join("__"), params).netzke_jsonify.to_json, :layout => false
95
+ end
10
96
 
11
97
  def set_controller_and_session
12
98
  Netzke::Base.controller = self
13
99
  Netzke::Base.session = session
14
100
  end
101
+
102
+ private
103
+
104
+ # inform AbstractController::Base that methods direct, ext, and dispatcher are actually actions
105
+ def action_method?(name)
106
+ %w(direct ext dispatcher).include?(name.to_s) || super
107
+ end
15
108
  end
16
109
  end
17
110
  end
@@ -1,10 +1,21 @@
1
1
  module ActionDispatch::Routing
2
2
  class Mapper
3
- # Enable routes for Netzke assets and endpoint calls. By default the URL is "/netzke", but this can be changed by providing an argument:
3
+ # Enables routes for Netzke assets and endpoint calls (by default routes to NetzkeController). The default URL is "/netzke", but this can be changed:
4
4
  #
5
5
  # netzke "/some/path/netzke"
6
- def netzke(prefix = "/netzke")
7
- match "#{prefix}/:action(.:format)", to: "netzke", as: 'netzke'
6
+ #
7
+ # If you want to use your own controller instead of NetzkeController, you can specify it like this:
8
+ #
9
+ # netzke "/netzke", controller: :admin
10
+ #
11
+ # This will make Netzke use AdminController. Note, that in that case AdminController MUST implement the actions required by Netzke. The way to do this is to include Netzke::Railz::ControllerExtensions in your controller, e.g.:
12
+ #
13
+ # class AdminController < ApplicationController
14
+ # include Netzke::Railz::ControllerExtensions
15
+ # end
16
+ def netzke(prefix = "/netzke", options = {})
17
+ controller = options[:controller] || :netzke
18
+ match "#{prefix}/:action(.:format)", to: controller.to_s, as: 'netzke'
8
19
  end
9
20
  end
10
21
  end
@@ -1,23 +1,9 @@
1
1
  class Array
2
- def deep_map(&block)
3
- self.map{ |el| el.respond_to?(:deep_map) ? block.call(el.deep_map(&block)) : block.call(el) }.compact
2
+ def netzke_deep_map(&block)
3
+ self.map{ |el| el.respond_to?(:netzke_deep_map) ? block.call(el.netzke_deep_map(&block)) : block.call(el) }.compact
4
4
  end
5
5
 
6
- def jsonify
7
- self.map{ |el| el.is_a?(Array) || el.is_a?(Hash) ? el.jsonify : el }
8
- end
9
-
10
- # Camelizes the keys of hashes and converts them to JSON
11
- def to_nifty_json
12
- self.jsonify.to_json
13
- end
14
-
15
- def deep_each_pair(&block)
16
- self.each{ |el| el.respond_to?('deep_each_pair') && el.deep_each_pair(&block) }
17
- end
18
-
19
- def deep_freeze
20
- each { |j| j.deep_freeze if j.respond_to? :deep_freeze }
21
- freeze
6
+ def netzke_jsonify
7
+ self.map{ |el| el.is_a?(Array) || el.is_a?(Hash) ? el.netzke_jsonify : el }
22
8
  end
23
9
  end
@@ -1,47 +1,41 @@
1
1
  class Hash
2
- def deep_map(&block)
2
+ def netzke_deep_map(&block)
3
3
  self.dup.tap do |h|
4
4
  h.each_pair do |k,v|
5
- h[k] = v.deep_map(&block) if v.respond_to?('deep_map')
5
+ h[k] = v.netzke_deep_map(&block) if v.respond_to?('netzke_deep_map')
6
6
  end
7
7
  end
8
8
  end
9
9
 
10
- def deep_each_pair(&block)
11
- self.each_pair do |k,v|
12
- v.respond_to?('deep_each_pair') ? v.deep_each_pair(&block) : yield(k,v)
13
- end
14
- end
15
-
16
- def jsonify
10
+ def netzke_jsonify
17
11
  self.inject({}) do |h,(k,v)|
18
- new_key = (k.is_a?(String) || k.is_a?(Symbol)) && !k.is_a?(ActiveSupport::JSON::Variable) ? k.jsonify : k
19
- new_value = v.is_a?(Array) || v.is_a?(Hash) ? v.jsonify : v
20
- h.merge(new_key => new_value)
21
- end
22
- end
12
+ new_key = if k.is_a?(ActiveSupport::JSON::Variable)
13
+ k
14
+ elsif k.is_a?(String)
15
+ k.camelize(:lower)
16
+ elsif k.is_a?(Symbol)
17
+ k.to_s.camelize(:lower).to_sym
18
+ else
19
+ k
20
+ end
23
21
 
24
- # First camelizes the keys, then convert the whole hash to JSON
25
- def to_nifty_json
26
- self.jsonify.to_json
27
- end
22
+ new_value = v.is_a?(Array) || v.is_a?(Hash) ? v.netzke_jsonify : v
28
23
 
29
- def deep_freeze
30
- each { |k,v| v.deep_freeze if v.respond_to? :deep_freeze }
31
- freeze
24
+ h.merge(new_key => new_value)
25
+ end
32
26
  end
33
27
 
34
28
  # From http://rubyworks.github.com/facets
35
- def update_keys #:yield:
29
+ def netzke_update_keys #:yield:
36
30
  if block_given?
37
31
  keys.each { |old_key| store(yield(old_key), delete(old_key)) }
38
32
  else
39
- to_enum(:update_keys)
33
+ to_enum(:netzke_update_keys)
40
34
  end
41
35
  end
42
36
 
43
- def literalize_keys
44
- update_keys{ |k| k.to_s.l }
37
+ def netzke_literalize_keys
38
+ netzke_update_keys{ |k| ActiveSupport::JSON::Variable.new(k.to_s) }
45
39
  self
46
40
  end
47
41
  end
@@ -4,4 +4,4 @@ module ActiveSupport
4
4
  self.to_s(:db).to_json
5
5
  end
6
6
  end
7
- end
7
+ end
@@ -1,5 +1,3 @@
1
1
  require "netzke/core/ruby_ext/array"
2
2
  require "netzke/core/ruby_ext/hash"
3
- require "netzke/core/ruby_ext/string"
4
- require "netzke/core/ruby_ext/symbol"
5
3
  require "netzke/core/ruby_ext/time_with_zone"
@@ -4,13 +4,20 @@ module Netzke::Core
4
4
  # Instance of this class is returned through component_session, and allows writing/reading to/from the session part reserved for a specific component (specified by component's js_id).
5
5
  class ComponentSessionProxy < Object
6
6
  def initialize(component_id)
7
- @session = Netzke::Base.session.nil? ? {} : Netzke::Base.session[component_id] ||= {}
7
+ @component_id = component_id
8
+ Netzke::Base.session ||= {}
9
+ Netzke::Base.session[:netzke_sessions] ||= {}
10
+ @session = Netzke::Base.session[:netzke_sessions][@component_id] ||= {}
8
11
  end
9
12
 
10
13
  # Delegate everything to session
11
14
  def method_missing(method, *args)
12
15
  @session.send(method, *args)
13
16
  end
17
+
18
+ def clear
19
+ Netzke::Base.session[:netzke_sessions].delete(@component_id)
20
+ end
14
21
  end
15
22
 
16
23
  # Component-specific session.
@@ -26,15 +26,15 @@ module Netzke::Core
26
26
  #
27
27
  # state[:position] #=> {:x => 100, :y => 200}
28
28
  #
29
- # May be overridden by persistence subsystems. The object returned by this should implement at least the following methods:
29
+ # May be overridden by persistence subsystems. The object returned by this should implement the following methods:
30
30
  #
31
31
  # * []
32
32
  # * []=
33
33
  # * delete(key)
34
34
  # * clear
35
35
  def state
36
- session[:state] ||= {}
37
- session[:state][persistence_key] ||= {}
36
+ session[:netzke_states] ||= {}
37
+ session[:netzke_states][persistence_key] ||= {}
38
38
  end
39
39
  end
40
40
  end
@@ -3,7 +3,7 @@ module Netzke
3
3
  module Version
4
4
  MAJOR = 0
5
5
  MINOR = 8
6
- PATCH = 1
6
+ PATCH = 2
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
9
9
  end