netzke-core 0.7.7 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/.travis.yml +1 -2
  2. data/CHANGELOG.md +572 -0
  3. data/LICENSE +7 -1
  4. data/README.md +345 -29
  5. data/Rakefile +3 -3
  6. data/app/controllers/netzke_controller.rb +37 -48
  7. data/config/ci/before-travis.sh +3 -4
  8. data/javascripts/base.js +86 -150
  9. data/javascripts/ext.js +180 -210
  10. data/javascripts/{core_extensions.js → js_extensions.js} +0 -0
  11. data/lib/netzke-core.rb +16 -6
  12. data/lib/netzke/base.rb +84 -107
  13. data/lib/netzke/core.rb +7 -41
  14. data/lib/netzke/core/action_config.rb +37 -0
  15. data/lib/netzke/core/actions.rb +123 -0
  16. data/lib/netzke/core/client_class.rb +252 -0
  17. data/lib/netzke/core/component_config.rb +12 -0
  18. data/lib/netzke/core/composition.rb +274 -0
  19. data/lib/netzke/core/config_to_dsl_delegator.rb +69 -0
  20. data/lib/netzke/core/configuration.rb +63 -0
  21. data/lib/netzke/core/css_config.rb +51 -0
  22. data/lib/netzke/core/dynamic_assets.rb +19 -49
  23. data/lib/netzke/{embedding.rb → core/embedding.rb} +4 -6
  24. data/lib/netzke/core/endpoint_response.rb +15 -0
  25. data/lib/netzke/core/javascript.rb +111 -0
  26. data/lib/netzke/core/panel.rb +11 -0
  27. data/lib/netzke/{plugins.rb → core/plugins.rb} +10 -5
  28. data/lib/netzke/core/railz.rb +4 -0
  29. data/lib/netzke/{railz → core/railz}/action_view_ext.rb +22 -18
  30. data/lib/netzke/core/railz/action_view_ext/ext.rb +49 -0
  31. data/lib/netzke/core/railz/controller_extensions.rb +17 -0
  32. data/lib/netzke/core/railz/engine.rb +16 -0
  33. data/lib/netzke/core/railz/routes.rb +10 -0
  34. data/lib/netzke/core/ruby_ext.rb +5 -0
  35. data/lib/netzke/core/ruby_ext/array.rb +23 -0
  36. data/lib/netzke/core/ruby_ext/hash.rb +47 -0
  37. data/lib/netzke/{core_ext → core/ruby_ext}/string.rb +2 -7
  38. data/lib/netzke/core/ruby_ext/symbol.rb +13 -0
  39. data/lib/netzke/{core_ext → core/ruby_ext}/time_with_zone.rb +0 -0
  40. data/lib/netzke/core/services.rb +130 -0
  41. data/lib/netzke/core/session.rb +15 -19
  42. data/lib/netzke/core/state.rb +40 -0
  43. data/lib/netzke/core/stylesheets.rb +48 -0
  44. data/lib/netzke/core/version.rb +2 -2
  45. data/lib/netzke/plugin.rb +8 -11
  46. data/netzke-core.gemspec +69 -59
  47. data/test/core_test_app/Gemfile +2 -20
  48. data/test/core_test_app/Gemfile.lock +65 -74
  49. data/test/core_test_app/app/components/card_component_loader.rb +4 -4
  50. data/test/core_test_app/app/components/component_loader.rb +40 -120
  51. data/test/core_test_app/app/components/component_loader/javascripts/component_loader.js +49 -0
  52. data/test/core_test_app/app/components/component_with_actions.rb +61 -47
  53. data/test/core_test_app/app/components/component_with_custom_css.rb +8 -5
  54. data/test/core_test_app/app/components/component_with_js_mixin.rb +11 -5
  55. data/test/core_test_app/app/components/component_with_js_mixin/javascripts/extra_one.js +1 -1
  56. data/test/core_test_app/app/components/component_with_js_mixin/javascripts/extra_two.js +1 -1
  57. data/test/core_test_app/app/components/component_with_js_mixin/javascripts/method_set_one.js +1 -1
  58. data/test/core_test_app/app/components/component_with_nested_through.rb +2 -2
  59. data/test/core_test_app/app/components/component_with_prebuilt_toolbar_control.rb +12 -0
  60. data/test/core_test_app/app/components/component_with_prebuilt_toolbar_control/javascripts/component_with_prebuilt_toolbar_control.js +12 -0
  61. data/test/core_test_app/app/components/component_with_required_js.rb +24 -0
  62. data/test/core_test_app/app/components/configurable_on_class_level.rb +8 -0
  63. data/test/core_test_app/app/components/dsl_delegated_properties.rb +4 -0
  64. data/test/core_test_app/app/components/dsl_delegated_properties_base.rb +5 -0
  65. data/test/core_test_app/app/components/dynamic_tab_panel/javascripts/dynamic_tab_panel.js +2 -2
  66. data/test/core_test_app/app/components/ext_direct/composite.rb +32 -33
  67. data/test/core_test_app/app/components/ext_direct/details.rb +2 -4
  68. data/test/core_test_app/app/components/ext_direct/selector.rb +20 -22
  69. data/test/core_test_app/app/components/ext_direct/statistics.rb +2 -4
  70. data/test/core_test_app/app/components/extended_component_with_actions.rb +7 -3
  71. data/test/core_test_app/app/components/extended_component_with_js_mixin.rb +7 -4
  72. data/test/core_test_app/app/components/extended_component_with_js_mixin/javascripts/some_method_set.js +1 -1
  73. data/test/core_test_app/app/components/extended_server_caller.rb +20 -14
  74. data/test/core_test_app/app/components/hello_world.rb +23 -0
  75. data/test/core_test_app/app/components/hello_world/javascripts/hello_world.js +12 -0
  76. data/test/core_test_app/app/components/included.js +2 -2
  77. data/test/core_test_app/app/components/kinda_complex_component.rb +1 -3
  78. data/test/core_test_app/app/components/kinda_complex_component/basic_stuff.rb +15 -17
  79. data/test/core_test_app/app/components/kinda_complex_component/extra_stuff.rb +4 -5
  80. data/test/core_test_app/app/components/loader_of_component_with_custom_css.rb +14 -5
  81. data/test/core_test_app/app/components/localized_panel.rb +23 -25
  82. data/test/core_test_app/app/components/multipane_component_loader.rb +19 -20
  83. data/test/core_test_app/app/components/nested_component.rb +4 -5
  84. data/test/core_test_app/app/components/panel_with_plugin.rb +8 -3
  85. data/test/core_test_app/app/components/panel_with_tools.rb +15 -14
  86. data/test/core_test_app/app/components/plugin_with_components.rb +20 -12
  87. data/test/core_test_app/app/components/scoped_components/deep_scoped_components/some_deep_scoped_component.rb +5 -2
  88. data/test/core_test_app/app/components/scoped_components/extended_scoped_component.rb +5 -2
  89. data/test/core_test_app/app/components/scoped_components/some_scoped_component.rb +5 -2
  90. data/test/core_test_app/app/components/server_caller.rb +39 -17
  91. data/test/core_test_app/app/components/server_caller/javascripts/server_caller.js +42 -0
  92. data/test/core_test_app/app/components/server_counter.rb +18 -82
  93. data/test/core_test_app/app/components/server_counter/javascripts/server_counter.js +53 -0
  94. data/test/core_test_app/app/components/simple_authentication_component.rb +46 -0
  95. data/test/core_test_app/app/components/simple_component.rb +8 -3
  96. data/test/core_test_app/app/components/simple_composite.rb +12 -0
  97. data/test/core_test_app/app/components/simple_form_with_file_upload.rb +49 -0
  98. data/test/core_test_app/app/components/simple_panel.rb +2 -2
  99. data/test/core_test_app/app/components/simple_tab_panel.rb +24 -3
  100. data/test/core_test_app/app/components/simple_window.rb +4 -2
  101. data/test/core_test_app/app/components/some_composite.rb +77 -48
  102. data/test/core_test_app/app/components/some_plugin.rb +31 -30
  103. data/test/core_test_app/app/components/stateful_component.rb +46 -0
  104. data/test/core_test_app/app/components/stateful_component_with_shared_state.rb +11 -0
  105. data/test/core_test_app/app/components/window_with_simple_component.rb +14 -0
  106. data/test/core_test_app/app/views/layouts/application.html.erb +1 -1
  107. data/test/core_test_app/app/views/simple_rails/multiple_nested.html.erb +7 -19
  108. data/test/core_test_app/app/views/simple_rails/panel.html.erb +1 -0
  109. data/test/core_test_app/config/database.yml.travis +3 -5
  110. data/test/core_test_app/config/environments/production.rb +1 -1
  111. data/test/core_test_app/config/initializers/netzke.rb +3 -1
  112. data/test/core_test_app/config/locales/en.yml +9 -4
  113. data/test/core_test_app/config/locales/es.yml +4 -2
  114. data/test/core_test_app/config/routes.rb +2 -8
  115. data/test/core_test_app/db/schema.rb +3 -11
  116. data/test/core_test_app/features/actions_and_tools.feature +1 -0
  117. data/test/core_test_app/features/client-server.feature +7 -0
  118. data/test/core_test_app/features/component_loader.feature +13 -13
  119. data/test/core_test_app/features/composition.feature +14 -0
  120. data/test/core_test_app/features/config_to_dsl_delegation.feature +10 -0
  121. data/test/core_test_app/features/file_inclusion.feature +1 -1
  122. data/test/core_test_app/features/i18n.feature +4 -4
  123. data/test/core_test_app/features/js_include.feature +1 -1
  124. data/test/core_test_app/features/persistence.feature +21 -5
  125. data/test/core_test_app/features/step_definitions/generic_steps.rb +14 -0
  126. data/test/core_test_app/features/support/paths.rb +0 -3
  127. data/test/core_test_app/public/images/icons/accept.png +0 -0
  128. data/test/core_test_app/public/images/icons/anchor.png +0 -0
  129. data/test/core_test_app/public/images/icons/tick.png +0 -0
  130. data/test/core_test_app/spec/action_config_spec.rb +15 -0
  131. data/test/core_test_app/spec/{component/actions_spec.rb → actions_spec.rb} +38 -36
  132. data/test/core_test_app/spec/base_spec.rb +35 -0
  133. data/test/core_test_app/spec/client_class_spec.rb +17 -0
  134. data/test/core_test_app/spec/component +0 -0
  135. data/test/core_test_app/spec/composition_spec.rb +118 -0
  136. data/test/core_test_app/spec/core_ext_spec.rb +3 -14
  137. data/test/core_test_app/spec/endpoint_response_spec.rb +17 -0
  138. data/test/core_test_app/spec/javascript_spec.rb +33 -0
  139. data/test/core_test_app/spec/js_class_config_scope.rb +37 -0
  140. data/test/core_test_app/spec/panel_spec.rb +11 -0
  141. data/test/core_test_app/spec/services_spec.rb +16 -0
  142. data/test/core_test_app/spec/state_spec.rb +20 -0
  143. data/test/unit/core_ext_test.rb +0 -53
  144. data/test/unit/netzke_core_test.rb +11 -11
  145. metadata +76 -62
  146. data/CHANGELOG.rdoc +0 -325
  147. data/javascripts/touch.js +0 -58
  148. data/lib/netzke/actions.rb +0 -107
  149. data/lib/netzke/composition.rb +0 -224
  150. data/lib/netzke/config_to_dsl_delegator.rb +0 -43
  151. data/lib/netzke/configuration.rb +0 -195
  152. data/lib/netzke/core/masquerading.rb +0 -34
  153. data/lib/netzke/core_ext.rb +0 -6
  154. data/lib/netzke/core_ext/array.rb +0 -30
  155. data/lib/netzke/core_ext/hash.rb +0 -86
  156. data/lib/netzke/core_ext/symbol.rb +0 -21
  157. data/lib/netzke/ext_component.rb +0 -25
  158. data/lib/netzke/inheritance.rb +0 -31
  159. data/lib/netzke/javascript.rb +0 -382
  160. data/lib/netzke/javascript/scopes.rb +0 -39
  161. data/lib/netzke/railz.rb +0 -4
  162. data/lib/netzke/railz/action_view_ext/ext.rb +0 -64
  163. data/lib/netzke/railz/action_view_ext/touch.rb +0 -52
  164. data/lib/netzke/railz/controller_extensions.rb +0 -33
  165. data/lib/netzke/railz/engine.rb +0 -48
  166. data/lib/netzke/railz/routes.rb +0 -7
  167. data/lib/netzke/services.rb +0 -101
  168. data/lib/netzke/session.rb +0 -54
  169. data/lib/netzke/state.rb +0 -91
  170. data/lib/netzke/stylesheets.rb +0 -65
  171. data/test/core_test_app/app/components/component_with_included_js.rb +0 -16
  172. data/test/core_test_app/app/components/component_with_session_persistence.rb +0 -35
  173. data/test/core_test_app/app/components/deprecated/server_caller.rb +0 -20
  174. data/test/core_test_app/app/components/dynamic_tab_panel.rb +0 -19
  175. data/test/core_test_app/app/components/hello_world_component.rb +0 -31
  176. data/test/core_test_app/app/components/touch/hello_world_component.rb +0 -25
  177. data/test/core_test_app/app/components/touch/server_caller.rb +0 -28
  178. data/test/core_test_app/app/components/touch/simple_carousel.rb +0 -17
  179. data/test/core_test_app/app/controllers/touch_controller.rb +0 -6
  180. data/test/core_test_app/app/helpers/touch_helper.rb +0 -2
  181. data/test/core_test_app/app/views/layouts/touch.html.erb +0 -13
  182. data/test/core_test_app/db/migrate/20110110132720_create_netzke_component_states.rb +0 -20
  183. data/test/core_test_app/features/step_definitions/touch_steps.rb +0 -3
  184. data/test/core_test_app/features/touch.feature +0 -10
  185. data/test/core_test_app/gemfiles/rails3_1.gemfile +0 -16
  186. data/test/core_test_app/gemfiles/rails3_2.gemfile +0 -16
  187. data/test/core_test_app/spec/component/base_spec.rb +0 -36
  188. data/test/core_test_app/spec/component/component_spec.rb +0 -20
  189. data/test/core_test_app/spec/component/composition_spec.rb +0 -132
  190. data/test/core_test_app/spec/component/configuration_spec.rb +0 -61
  191. data/test/core_test_app/spec/component/javascript_spec.rb +0 -16
  192. data/test/core_test_app/spec/component/state_spec.rb +0 -18
@@ -0,0 +1,4 @@
1
+ require 'netzke/core/railz/engine'
2
+ require 'netzke/core/railz/routes'
3
+ require 'netzke/core/railz/action_view_ext'
4
+ require 'netzke/core/railz/controller_extensions'
@@ -1,26 +1,30 @@
1
- require 'netzke/railz/action_view_ext/ext'
2
- require 'netzke/railz/action_view_ext/touch'
1
+ require 'netzke/core/railz/action_view_ext/ext'
3
2
  module Netzke
4
3
  module Railz
5
4
  module ActionViewExt
6
5
  include Ext
7
- include Touch
8
6
 
9
- # A helper to initialize Netzke. Usually used in the layout.
7
+ # A helper to load Netzke and Ext JS files. Usually used in the layout.
10
8
  #
11
9
  # Params:
12
- # * :platform - :ext or :touch, by default :ext
13
- # * :theme - the name of theme to apply
14
- # * :cache - enable Rails caching of assets
10
+ #
11
+ # * :theme - the name of theme to apply; follows simple convention of including css files named "ext-(theme)".
15
12
  #
16
13
  # E.g.:
17
- # <%= netzke_init :theme => :grey %>
18
14
  #
19
- # For Sencha Touch:
20
- # <%= netzke_init :platform => :touch %>
21
- def netzke_init(params = {})
15
+ # <%= load_netzke theme: "neptune" %>
16
+ #
17
+ # Other theme options that may work (unless Sencha introduces some/other conventions):
18
+ #
19
+ # - all (standard)
20
+ # - all-gray
21
+ # - all-access
22
+ #
23
+ # * :minified - set to +true+ to load minified JS and CSS for Ext JS also in development env
24
+ def load_netzke(params = {})
22
25
  Netzke::Core.platform = params[:platform] || :ext
23
- theme = params[:theme] || params[:ext_theme]
26
+ params[:minified] = !Rails.env.development? if params[:minified].nil?
27
+ params[:theme] ||= :all
24
28
 
25
29
  raw([netzke_css_include(params), netzke_css(params), netzke_js_include(params), netzke_js(params)].join("\n"))
26
30
  end
@@ -40,11 +44,11 @@ module Netzke
40
44
 
41
45
  config[:name] = name
42
46
 
43
- # Register the component in session
44
- Netzke::Core.reg_component(config)
45
-
46
47
  cmp = Netzke::Base.instance_by_config(config)
47
- cmp.before_load # inform the component about initial load
48
+
49
+ # Register the component in session
50
+ session[:netzke_components] ||= {}
51
+ session[:netzke_components][cmp.js_id.to_sym] = config
48
52
 
49
53
  content_for :netzke_js_classes, raw(cmp.js_missing_code(@rendered_classes))
50
54
 
@@ -53,7 +57,7 @@ module Netzke
53
57
  content_for :netzke_on_ready, raw("#{cmp.js_component_instance}\n\n#{cmp.js_component_render}")
54
58
 
55
59
  # Now mark all this component's dependency classes (including self) as rendered (by storing their xtypes), so that we only generate a class once per view
56
- @rendered_classes = (@rendered_classes + cmp.dependency_classes.map(&:js_xtype)).uniq
60
+ @rendered_classes = (@rendered_classes + cmp.dependency_classes.map{|k| k.js_config.xtype}).uniq
57
61
 
58
62
  # Return the html for this component
59
63
  raw(cmp.js_component_html)
@@ -79,7 +83,7 @@ module Netzke
79
83
  send :"netzke_#{Netzke::Core.platform}_js_include", params
80
84
  end
81
85
 
82
- # Inline JavaScript for all Netzke classes on the page, as well as Ext.onReady (Ext.setup in case of Touch) which renders Netzke components in this view after the page is loaded
86
+ # Inline JavaScript for all Netzke classes on the page, as well as Ext.onReady, which renders Netzke components in this view after the page is loaded
83
87
  def netzke_js(params = {})
84
88
  send :"netzke_#{Netzke::Core.platform}_js", params
85
89
  end
@@ -0,0 +1,49 @@
1
+ module Netzke
2
+ module Railz
3
+ module ActionViewExt
4
+ # Implementation of Ext-specific Netzke helpers
5
+ module Ext
6
+
7
+ private
8
+
9
+ def netzke_ext_css_include(params)
10
+ # ExtJS base
11
+ res = ["#{Netzke::Core.ext_uri}/resources/css/ext-#{params[:theme]}"]
12
+
13
+ # Netzke-related dynamic css
14
+ res << netzke_path(:ext)
15
+
16
+ res += Netzke::Core.external_ext_css
17
+
18
+ stylesheet_link_tag(*res)
19
+ end
20
+
21
+ def netzke_ext_js_include(params)
22
+ res = []
23
+
24
+ # ExtJS
25
+ res << (params[:minified] ? "#{Netzke::Core.ext_uri}/ext-all" : "#{Netzke::Core.ext_uri}/ext-all-debug")
26
+
27
+ # Ext I18n
28
+ res << "#{Netzke::Core.ext_uri}/locale/ext-lang-#{I18n.locale}" if I18n.locale != :en
29
+
30
+ # Netzke-related dynamic JavaScript
31
+ res << netzke_path(:ext)
32
+
33
+ javascript_include_tag(*res)
34
+ end
35
+
36
+ def netzke_ext_js(params)
37
+ res = []
38
+ res << content_for(:netzke_js_classes)
39
+
40
+ res << "Ext.onReady(function(){"
41
+ res << content_for(:netzke_on_ready)
42
+ res << "});"
43
+
44
+ javascript_tag(res.join("\n"))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ module Netzke
2
+ module Railz
3
+ # Before each request, Netzke::Base.controller and Netzke::Base.session are set, to be accessible from components.
4
+ module ControllerExtensions
5
+ def self.included(base)
6
+ base.send(:before_filter, :set_controller_and_session)
7
+ end
8
+
9
+ protected
10
+
11
+ def set_controller_and_session
12
+ Netzke::Base.controller = self
13
+ Netzke::Base.session = session
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Netzke
2
+ module Railz
3
+ class Engine < Rails::Engine
4
+ initializer "netzke.core" do |app|
5
+ app.config.eager_load_paths -= ["#{app.config.root}/app/components"]
6
+ app.config.autoload_paths += ["#{app.config.root}/app/components"]
7
+ end
8
+
9
+ # before loading initializers
10
+ config.before_initialize do |app|
11
+ Netzke::Core.ext_path = Rails.root.join('public', Netzke::Core.ext_uri[1..-1])
12
+ Netzke::Core.with_icons = File.exists?("#{::Rails.root}/public#{Netzke::Core.icons_uri}") if Netzke::Core.with_icons.nil?
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ module ActionDispatch::Routing
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:
4
+ #
5
+ # netzke "/some/path/netzke"
6
+ def netzke(prefix = "/netzke")
7
+ match "#{prefix}/:action(.:format)", to: "netzke", as: 'netzke'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ require "netzke/core/ruby_ext/array"
2
+ require "netzke/core/ruby_ext/hash"
3
+ require "netzke/core/ruby_ext/string"
4
+ require "netzke/core/ruby_ext/symbol"
5
+ require "netzke/core/ruby_ext/time_with_zone"
@@ -0,0 +1,23 @@
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
4
+ end
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
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ class Hash
2
+ def deep_map(&block)
3
+ self.dup.tap do |h|
4
+ h.each_pair do |k,v|
5
+ h[k] = v.deep_map(&block) if v.respond_to?('deep_map')
6
+ end
7
+ end
8
+ end
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
17
+ 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
23
+
24
+ # First camelizes the keys, then convert the whole hash to JSON
25
+ def to_nifty_json
26
+ self.jsonify.to_json
27
+ end
28
+
29
+ def deep_freeze
30
+ each { |k,v| v.deep_freeze if v.respond_to? :deep_freeze }
31
+ freeze
32
+ end
33
+
34
+ # From http://rubyworks.github.com/facets
35
+ def update_keys #:yield:
36
+ if block_given?
37
+ keys.each { |old_key| store(yield(old_key), delete(old_key)) }
38
+ else
39
+ to_enum(:update_keys)
40
+ end
41
+ end
42
+
43
+ def literalize_keys
44
+ update_keys{ |k| k.to_s.l }
45
+ self
46
+ end
47
+ end
@@ -1,14 +1,10 @@
1
1
  class String
2
2
  def jsonify
3
- if self.index('_') == 0
4
- # '_some_string' should become '_someString' and not 'SomeString'
5
- '_' + self[1..-1].camelize(:lower)
6
- else
7
- self.camelize(:lower)
8
- end
3
+ self.camelize(:lower)
9
4
  end
10
5
 
11
6
  # Converts self to "literal JSON"-string - one that doesn't get quotes appended when being sent "to_json" method
7
+ # TODO: get rid of it
12
8
  def l
13
9
  ActiveSupport::JSON::Variable.new(self)
14
10
  end
@@ -27,5 +23,4 @@ class String
27
23
  def to_b
28
24
  self != "false"
29
25
  end
30
-
31
26
  end
@@ -0,0 +1,13 @@
1
+ class Symbol
2
+ def jsonify
3
+ self.to_s.camelize(:lower).to_sym
4
+ end
5
+
6
+ def l
7
+ ActiveSupport::JSON::Variable.new(self.to_s)
8
+ end
9
+
10
+ def to_cls_attr
11
+ "__#{self}__".to_sym
12
+ end
13
+ end
@@ -0,0 +1,130 @@
1
+ module Netzke::Core
2
+ # The client-server communication between the JavaScript and Ruby side of a component is provided by means of "endpoints".
3
+ #
4
+ # == Defining an endpoint
5
+ #
6
+ # An endpoint is defined through the +endpoint+ class method on the Ruby class:
7
+ #
8
+ # endpoint :do_something do |params, this|
9
+ # # ...
10
+ # end
11
+ #
12
+ # The first block argument will contain the hash of arguments provided at the moment of calling the endpoint from the JavaScript side (see "Calling an endpoint from JavaScript").
13
+ # The second block argument is used for "calling" JavaScript methods as a response from the server (see "Envoking JavaScript methods from the server").
14
+ #
15
+ # == Calling an endpoint from JavaScript
16
+ #
17
+ # By defining the endpoint on the Ruby class, the client side automatically gets an equally named (but camelcased) method that is used to call the endpoint at the server. In the previous example, that would be +doSomething+. Its signature goes as follows:
18
+ #
19
+ # this.doSomething(argsObject, callbackFunction, scope);
20
+ #
21
+ # * +argsObject+ is what the server side will receive as the +params+ argument
22
+ # * +callbackFunction+ (optional) will be called after the server successfully processes the request
23
+ # * +scope+ (optional) the scope in which +callbackFunction+ will be called
24
+ #
25
+ # The callback function can optionally receive an argument set by the endpoint at the server (see "Providing the argument to the callback function").
26
+ #
27
+ # == Envoking JavaScript methods from the server
28
+ #
29
+ # An endpoint, after doing some useful job at the server, is able to instruct the client side of the component to call multiple methods (preserving the call order) with provided arguments. It's done by using the second parameter of the endpoint block (which is illustratively called 'this'):
30
+ #
31
+ # endpoint :do_something do |params, this|
32
+ # # ... do the thing
33
+ # this.set_title("New title")
34
+ # this.add_class("some-extra-css")
35
+ # end
36
+ #
37
+ # This will result in successive calling the +setTitle+ and +addClass+ methods on the JavaScript instance of our component.
38
+ #
39
+ # Besides "calling" methods on the current component itself, it's also possible to address its instantiated children at any level of the hierarchy:
40
+ #
41
+ # endpoint :do_something do |params, this|
42
+ # # ... do the thing
43
+ # this.east_panel_component.set_title("New east panel title")
44
+ # this.east_panel_component.deep_nested_component.do_something_very_special("With", "some", "arguments")
45
+ # end
46
+ #
47
+ # == Providing arguments to the callback function
48
+ #
49
+ # The callback function provided at the moment of calling an endpoint may receive an argument set by the endpoint by "calling" the special +netzke_set_result+ method. :
50
+ #
51
+ # endpoint :do_something do |params, this|
52
+ # # ... do the thing
53
+ # this.netzke_set_result(42)
54
+ # end
55
+ #
56
+ # By calling the endpoint from the client side like this:
57
+ #
58
+ # this.doSomething({}, function(result){ console.debug(result); });
59
+ #
60
+ # ... the value of +result+ after the execution of the endpoint will be set to 42. Using this mechanism can be seen as doing an asyncronous call to a function at the server, which returns a value.
61
+ #
62
+ # == Overriding an endpoint
63
+ #
64
+ # When overriding an endpoint, you can call the original endpoint by using +super+ and explicitely providing the block parameters to it:
65
+ #
66
+ # endpoint :do_something do |params, this|
67
+ # super(params, this)
68
+ # this.doMore
69
+ # end
70
+ #
71
+ # If you want to reuse the original arguments set in +super+, you can access them from the +this+ object. Provided we are overriding the +do_something+ endpoint from the example in "Envoking JavaScript methods from the server", we will have:
72
+ #
73
+ # endpoint :do_something do |params, this|
74
+ # super(params, this)
75
+ # original_arguments_for_set_title = this.set_title # => ["New title"]
76
+ # original_arguments_for_add_class = this.add_class # => ["some-extra-css"]
77
+ # end
78
+ module Services
79
+ extend ActiveSupport::Concern
80
+
81
+ included do
82
+ # Returns all endpoints as a hash
83
+ class_attribute :endpoints
84
+ self.endpoints = {}
85
+ end
86
+
87
+ module ClassMethods
88
+ def endpoint(name, options = {}, &block)
89
+ register_endpoint(name)
90
+ define_method("#{name}_endpoint", &block)
91
+ end
92
+
93
+ protected
94
+
95
+ # Registers an endpoint at the class level
96
+ def register_endpoint(ep)
97
+ self.endpoints = self.endpoints.dup if self.superclass.respond_to?(:endpoints) && self.endpoints == self.superclass.endpoints # only dup for the first endpoint declaration
98
+ self.endpoints[ep.to_sym] = true
99
+ end
100
+ end
101
+
102
+ # Invokes an endpoint call
103
+ # +endpoint+ may contain the path to the endpoint in a component down the hierarchy, e.g.:
104
+ #
105
+ # invoke_endpoint(:users__center__get_data, params)
106
+ def invoke_endpoint(endpoint, params)
107
+ if self.class.endpoints[endpoint.to_sym]
108
+ endpoint_response = Netzke::Core::EndpointResponse.new
109
+ send("#{endpoint}_endpoint", params, endpoint_response)
110
+
111
+ endpoint_response
112
+ else
113
+ # Let's try to find it recursively in a component down the hierarchy
114
+ child_component, *action = endpoint.to_s.split('__')
115
+ child_component = child_component.to_sym
116
+ action = !action.empty? && action.join("__").to_sym
117
+
118
+ raise RuntimeError, "Component '#{self.class.name}' does not have endpoint '#{endpoint}'" if !action
119
+
120
+ if components[child_component]
121
+ component_instance(child_component).invoke_endpoint(action, params)
122
+ else
123
+ # component_missing can be overridden if necessary
124
+ component_missing(child_component)
125
+ end
126
+ end
127
+ end
128
+
129
+ end
130
+ end
@@ -1,25 +1,21 @@
1
- module Netzke
2
- module Core
3
- module Session
4
- # Should be called by session controller at the moment of successfull login
5
- def login
6
- session[:_netzke_next_request_is_first_after_login] = true
1
+ module Netzke::Core
2
+ # Implements component-specific session manupulation.
3
+ module Session
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
+ class ComponentSessionProxy < Object
6
+ def initialize(component_id)
7
+ @session = Netzke::Base.session.nil? ? {} : Netzke::Base.session[component_id] ||= {}
7
8
  end
8
9
 
9
- # Should be called by session controller at the moment of logout
10
- def logout
11
- session[:_netzke_next_request_is_first_after_logout] = true
12
- end
13
-
14
- def current_user
15
- Netzke::Core.controller.respond_to?(Netzke::Core.current_user_method) && Netzke::Core.controller.send(Netzke::Core.current_user_method) || nil
10
+ # Delegate everything to session
11
+ def method_missing(method, *args)
12
+ @session.send(method, *args)
16
13
  end
14
+ end
17
15
 
18
- # Register the configuration for the component in the session, and also remember that the code for it has been rendered
19
- def reg_component(config)
20
- session[:netzke_components] ||= {}
21
- session[:netzke_components][config[:name]] = config
22
- end
16
+ # Component-specific session.
17
+ def component_session
18
+ @component_session_proxy ||= ComponentSessionProxy.new(js_id)
23
19
  end
24
20
  end
25
- end
21
+ end