netzke-core 0.12.3 → 1.0.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +65 -607
- data/Gemfile +1 -1
- data/LICENSE +2 -6
- data/README.md +77 -145
- data/javascripts/base.js +582 -96
- data/javascripts/core.js +62 -0
- data/javascripts/notifications.js +43 -0
- data/javascripts/remoting_provider.js +29 -0
- data/javascripts/routing.js +63 -0
- data/lib/netzke/base.rb +16 -83
- data/lib/netzke/core/action_config.rb +1 -5
- data/lib/netzke/core/actions.rb +59 -21
- data/lib/netzke/core/{client_class.rb → client_class_config.rb} +81 -73
- data/lib/netzke/core/client_code.rb +157 -0
- data/lib/netzke/core/component_config.rb +2 -2
- data/lib/netzke/core/composition.rb +85 -65
- data/lib/netzke/core/configuration.rb +26 -14
- data/lib/netzke/core/core_i18n.rb +17 -0
- data/lib/netzke/core/css_config.rb +6 -6
- data/lib/netzke/core/dynamic_assets.rb +17 -24
- data/lib/netzke/core/embedding.rb +2 -2
- data/lib/netzke/core/endpoint_response.rb +8 -2
- data/lib/netzke/core/inheritance.rb +33 -0
- data/lib/netzke/core/plugins.rb +1 -4
- data/lib/netzke/core/railz/action_view_ext.rb +1 -1
- data/lib/netzke/core/railz/controller_extensions.rb +21 -15
- data/lib/netzke/core/services.rb +61 -48
- data/lib/netzke/core/session.rb +0 -2
- data/lib/netzke/core/state.rb +11 -9
- data/lib/netzke/core/stylesheets.rb +3 -3
- data/lib/netzke/core/version.rb +1 -1
- data/lib/netzke/core.rb +3 -3
- data/lib/netzke/plugin.rb +2 -6
- data/stylesheets/core.css +2 -2
- metadata +11 -10
- data/TODO.md +0 -9
- data/javascripts/ext.js +0 -518
- data/lib/netzke/core/config_to_dsl_delegator.rb +0 -62
- data/lib/netzke/core/dsl_support.rb +0 -70
- data/lib/netzke/core/html.rb +0 -29
- data/lib/netzke/core/javascript.rb +0 -123
@@ -5,7 +5,7 @@ module Netzke::Core
|
|
5
5
|
# class_attribute :title
|
6
6
|
# self.title = "Title for all descendants of MyComponent"
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# client_class do |c|
|
9
9
|
# c.title = title
|
10
10
|
# end
|
11
11
|
# end
|
@@ -28,14 +28,30 @@ module Netzke::Core
|
|
28
28
|
# config.enable_awesome_feature = true
|
29
29
|
# end
|
30
30
|
module ClassMethods
|
31
|
+
# Do class-level config of a component, e.g.:
|
32
|
+
#
|
33
|
+
# Netzke::Basepack::GridPanel.setup do |c|
|
34
|
+
# c.rows_reordering_available = false
|
35
|
+
# end
|
31
36
|
def setup
|
32
37
|
yield self
|
33
38
|
end
|
34
39
|
|
35
40
|
# An array of server class config options that should not be passed to the client class. Can be overridden.
|
36
41
|
def server_side_config_options
|
37
|
-
[:
|
42
|
+
[:klass, :client_config]
|
38
43
|
end
|
44
|
+
|
45
|
+
# Instance of component by config
|
46
|
+
def instance_by_config(config)
|
47
|
+
klass = config[:klass] || config[:class_name].constantize
|
48
|
+
klass.new(config)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
included do
|
53
|
+
# Config that has all the config extensions applied (via `extend_item`)
|
54
|
+
attr_accessor :normalized_config
|
39
55
|
end
|
40
56
|
|
41
57
|
# Override to auto-configure components. Example:
|
@@ -60,7 +76,7 @@ module Netzke::Core
|
|
60
76
|
@config ||= ActiveSupport::OrderedOptions.new
|
61
77
|
end
|
62
78
|
|
63
|
-
# Config options that have been set on the fly on the client side of the component in the `
|
79
|
+
# Config options that have been set on the fly on the client side of the component in the `serverConfig` object. Can be
|
64
80
|
# used to dynamically change component configuration. Those changes won't affect the way component is rendered, of
|
65
81
|
# course, but can be useful to reconfigure child components, e.g.:
|
66
82
|
#
|
@@ -69,7 +85,7 @@ module Netzke::Core
|
|
69
85
|
# this.callParent();
|
70
86
|
#
|
71
87
|
# this.netzkeGetComponent('authors').on('rowclick', function(grid, record) {
|
72
|
-
# this.
|
88
|
+
# this.serverConfig.author_id = record.getId();
|
73
89
|
# this.netzkeGetComponent('book_grid').getStore().load();
|
74
90
|
# }
|
75
91
|
# }
|
@@ -82,13 +98,14 @@ module Netzke::Core
|
|
82
98
|
ActiveSupport::OrderedOptions.new.merge!(config.client_config)
|
83
99
|
end
|
84
100
|
|
85
|
-
|
101
|
+
protected
|
86
102
|
|
87
|
-
# Override to validate
|
103
|
+
# Override to validate or enforce certain configuration options
|
88
104
|
# E.g.:
|
89
105
|
#
|
90
106
|
# def validate_config(c)
|
91
107
|
# raise ArgumentError, "Grid requires a model" if c.model.nil?
|
108
|
+
# c.paging = true if c.edit_inline
|
92
109
|
# end
|
93
110
|
def validate_config(c)
|
94
111
|
end
|
@@ -104,12 +121,13 @@ module Netzke::Core
|
|
104
121
|
|
105
122
|
# We'll build a couple of useful instance variables here:
|
106
123
|
#
|
107
|
-
# +components_in_config+ - an array of components (by name) referred in
|
124
|
+
# +components_in_config+ - an array of components (by name) referred in `configure`
|
125
|
+
# +inline_components+ - a hash with configs of components defined inline in `configure`
|
108
126
|
# +normalized_config+ - a config that has all the config extensions applied
|
109
127
|
def normalize_config
|
110
|
-
# @actions = @components = {} # in v1.0 this should replace DSL definition
|
111
128
|
@components_in_config = []
|
112
129
|
@implicit_component_index = 0
|
130
|
+
@inline_components = {}
|
113
131
|
c = config.dup
|
114
132
|
config.each_pair do |k, v|
|
115
133
|
c.delete(k) if self.class.server_side_config_options.include?(k.to_sym)
|
@@ -119,11 +137,5 @@ module Netzke::Core
|
|
119
137
|
end
|
120
138
|
@normalized_config = c
|
121
139
|
end
|
122
|
-
|
123
|
-
# @return [Hash] config with all placeholders (like child components referred by symbols) expanded
|
124
|
-
def normalized_config
|
125
|
-
# make sure we call normalize_config first
|
126
|
-
@normalized_config || (normalize_config || true) && @normalized_config
|
127
|
-
end
|
128
140
|
end
|
129
141
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Core
|
3
|
+
module CoreI18n
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
module ClassMethods
|
6
|
+
# The ID used to locate this component's block in locale files
|
7
|
+
def i18n_id
|
8
|
+
name.split("::").map{|c| c.underscore}.join(".")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def i18n_id
|
13
|
+
self.class.i18n_id
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Netzke
|
2
2
|
module Core
|
3
|
-
# This class is responsible of assemblage of stylesheet dependencies. It is passed as block parameter to the +
|
3
|
+
# This class is responsible of assemblage of stylesheet dependencies. It is passed as block parameter to the +client_styles+ DSL method:
|
4
4
|
#
|
5
5
|
# class MyComponent < Netzke::Base
|
6
|
-
#
|
6
|
+
# client_styles do |c|
|
7
7
|
# c.require :extra_styles
|
8
8
|
# end
|
9
9
|
# end
|
@@ -23,16 +23,16 @@ module Netzke
|
|
23
23
|
# Symbols will be expanded following a convention, e.g.:
|
24
24
|
#
|
25
25
|
# class MyComponent < Netzke::Base
|
26
|
-
#
|
26
|
+
# client_styles do |c|
|
27
27
|
# c.require :some_styles
|
28
28
|
# end
|
29
29
|
# end
|
30
30
|
#
|
31
|
-
# This will "require" a stylesheet file +{component_location}/my_component/
|
31
|
+
# This will "require" a stylesheet file +{component_location}/my_component/client/some_styles.css+
|
32
32
|
#
|
33
33
|
# Strings will be interpreted as full paths to the required JavaScript file:
|
34
34
|
#
|
35
|
-
#
|
35
|
+
# client_styles do |c|
|
36
36
|
# c.require "#{File.dirname(__FILE__)}/my_component/one.css", "#{File.dirname(__FILE__)}/my_component/two.css"
|
37
37
|
# end
|
38
38
|
def require(*args)
|
@@ -43,7 +43,7 @@ module Netzke
|
|
43
43
|
private
|
44
44
|
|
45
45
|
def expand_css_require_path(sym, callr)
|
46
|
-
%Q(#{callr.split(".rb:").first}/
|
46
|
+
%Q(#{callr.split(".rb:").first}/client/#{sym}.css)
|
47
47
|
end
|
48
48
|
|
49
49
|
end
|
@@ -3,14 +3,13 @@ require 'uglifier'
|
|
3
3
|
module Netzke
|
4
4
|
module Core
|
5
5
|
module DynamicAssets
|
6
|
+
CORE_FILES = %w[js_extensions core notifications remoting_provider base routing]
|
7
|
+
|
6
8
|
class << self
|
7
9
|
def ext_js(form_authenticity_token)
|
8
10
|
res = initial_dynamic_javascript(form_authenticity_token) << "\n"
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
# Ext-specific JavaScript
|
13
|
-
res << File.new(File.expand_path("../../../../javascripts/ext.js", __FILE__)).read
|
12
|
+
include_core_js(res)
|
14
13
|
|
15
14
|
# Pluggable JavaScript (used by other Netzke-powered gems like netzke-basepack)
|
16
15
|
Netzke::Core.ext_javascripts.each do |path|
|
@@ -35,7 +34,7 @@ module Netzke
|
|
35
34
|
|
36
35
|
def minify_js(js_string)
|
37
36
|
if ::Rails.env.test? || ::Rails.env.development?
|
38
|
-
js_string
|
37
|
+
js_string.gsub(/\/\*\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//, '') # strip docs
|
39
38
|
else
|
40
39
|
Uglifier.compile(js_string)
|
41
40
|
end
|
@@ -45,28 +44,22 @@ module Netzke
|
|
45
44
|
|
46
45
|
# Generates initial javascript code that is dependent on Rails settings
|
47
46
|
def initial_dynamic_javascript(form_authenticity_token)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
res << %{Netzke.core.FeedbackDelay = #{Netzke::Core.js_feedback_delay};}
|
58
|
-
|
59
|
-
res.join("\n")
|
47
|
+
url_root = ActionController::Base.config.relative_url_root
|
48
|
+
%(Ext.Ajax.setExtraParams({authenticity_token: '#{form_authenticity_token}'});
|
49
|
+
Ext.ns('Netzke.Core');
|
50
|
+
Netzke.RelativeUrlRoot = '#{url_root}';
|
51
|
+
Netzke.ControllerUrl = '#{url_root}#{Rails.application.routes.url_helpers.netzke_path}/';
|
52
|
+
Netzke.RelativeExtUrl = '#{url_root}#{Netzke::Core.ext_uri}';
|
53
|
+
Netzke.Core.directMaxRetries = #{Netzke::Core.js_direct_max_retries};
|
54
|
+
Netzke.Core.NotificationDelay = #{Netzke::Core.client_notification_delay};
|
55
|
+
)
|
60
56
|
end
|
61
57
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# Base Netzke component JavaScript
|
67
|
-
arry << File.new(File.expand_path("../../../../javascripts/base.js", __FILE__)).read
|
58
|
+
def include_core_js(arry)
|
59
|
+
CORE_FILES.each do |script|
|
60
|
+
arry << File.new(File.expand_path("../../../../javascripts/#{script}.js", __FILE__)).read
|
61
|
+
end
|
68
62
|
end
|
69
|
-
|
70
63
|
end
|
71
64
|
end
|
72
65
|
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.to_s.camelize(:lower)} = Ext.create("#{self.class.
|
6
|
+
%Q{Netzke.page.#{name.to_s.camelize(:lower)} = Ext.create("#{self.class.client_class_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.to_s.camelize(:lower)}.render("#{name.to_s.split('_').join('-')}-netzke");} unless self.class.
|
11
|
+
%Q{Netzke.page.#{name.to_s.camelize(:lower)}.render("#{name.to_s.split('_').join('-')}-netzke");} unless self.class.client_class_config.xtype == "netzkewindow"
|
12
12
|
end
|
13
13
|
|
14
14
|
# Container for rendering
|
@@ -1,6 +1,12 @@
|
|
1
1
|
module Netzke::Core
|
2
|
-
# Represents the endpoint response at the server side.
|
3
|
-
#
|
2
|
+
# Represents the endpoint response at the server side. Collects instructions for the client-side object. Accessible as
|
3
|
+
# the `client` in the endpoint calls, e.g.:
|
4
|
+
#
|
5
|
+
# class SimpleComponent < Netzke::Base
|
6
|
+
# endpoint :whats_up_server do
|
7
|
+
# client.set_title("Response from server")
|
8
|
+
# end
|
9
|
+
# end
|
4
10
|
class EndpointResponse < ::Hash
|
5
11
|
def method_missing(name, *params)
|
6
12
|
if name.to_s =~ /(.+)=$/
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Core
|
3
|
+
module Inheritance
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
module ClassMethods
|
6
|
+
attr_accessor :called_from
|
7
|
+
|
8
|
+
# Ancestor classes in the Netzke class hierarchy up to (and excluding) +Netzke::Base+, including self; in comparison to Ruby's own Class.ancestors, the order is reversed.
|
9
|
+
def netzke_ancestors
|
10
|
+
if self == Netzke::Base
|
11
|
+
[]
|
12
|
+
else
|
13
|
+
superclass.netzke_ancestors + [self]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Keep track of component's file. Inspired by Rails railties code.
|
18
|
+
def inherited(base)
|
19
|
+
base.called_from = begin
|
20
|
+
cllr = if Kernel.respond_to?(:caller_locations)
|
21
|
+
location = caller_locations.first
|
22
|
+
location.absolute_path || location.path
|
23
|
+
else
|
24
|
+
caller.first
|
25
|
+
end
|
26
|
+
|
27
|
+
cllr.split(".rb").first
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/netzke/core/plugins.rb
CHANGED
@@ -12,11 +12,8 @@ module Netzke::Core
|
|
12
12
|
# Defines a plugin
|
13
13
|
def plugin(name, &block)
|
14
14
|
register_plugin(name)
|
15
|
-
component name do |c|
|
15
|
+
component name, eager_load: true do |c|
|
16
16
|
block.call(c) if block_given?
|
17
|
-
|
18
|
-
# plugins are *always* eagerly loaded
|
19
|
-
c.eager_loading = true
|
20
17
|
end
|
21
18
|
end
|
22
19
|
|
@@ -54,7 +54,7 @@ module Netzke
|
|
54
54
|
content_for :netzke_on_ready, raw("#{cmp.js_component_instance}\n\n#{cmp.js_component_render}")
|
55
55
|
|
56
56
|
# 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
|
57
|
-
@rendered_classes = (@rendered_classes + cmp.dependency_classes.map{|k| k.
|
57
|
+
@rendered_classes = (@rendered_classes + cmp.dependency_classes.map{|k| k.client_class_config.xtype}).uniq
|
58
58
|
|
59
59
|
# Return the html for this component
|
60
60
|
raw(cmp.js_component_html)
|
@@ -15,15 +15,13 @@ module Netzke
|
|
15
15
|
@params[:endpoint].underscore
|
16
16
|
end
|
17
17
|
|
18
|
+
# arguments for endpoint call
|
18
19
|
def args
|
19
|
-
|
20
|
-
#
|
21
|
-
remoting_args.has_key?("args") ? remoting_args["args"] : remoting_args.reject{|k,v| k == 'configs' }
|
20
|
+
res = remoting_args.has_key?("args") ? remoting_args["args"] : remoting_args
|
21
|
+
res.is_a?(Array) ? res : [res].compact # need to wrap into array to normalize
|
22
22
|
end
|
23
23
|
|
24
24
|
def client_configs
|
25
|
-
# if no configs are provided, the behavior is the old one, and thus all instances the same child component
|
26
|
-
# will be treated as one
|
27
25
|
remoting_args["configs"] || []
|
28
26
|
end
|
29
27
|
|
@@ -33,8 +31,9 @@ module Netzke
|
|
33
31
|
|
34
32
|
private
|
35
33
|
|
34
|
+
# raw arguments from the client
|
36
35
|
def remoting_args
|
37
|
-
@_remoting_args ||= @params[:data]
|
36
|
+
@_remoting_args ||= @params[:data]
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
@@ -87,6 +86,7 @@ module Netzke
|
|
87
86
|
|
88
87
|
protected
|
89
88
|
|
89
|
+
# Receives DirectRequest and result of invoke_endpoint, returns hash understood by client-side's Direct function
|
90
90
|
def direct_response(request, endpoint_response)
|
91
91
|
component_name, *sub_components = request.cmp_path.split('__')
|
92
92
|
|
@@ -101,17 +101,16 @@ module Netzke
|
|
101
101
|
}
|
102
102
|
end
|
103
103
|
|
104
|
+
# Receives DirectRequest, returns an array/hash of methods for the client side (consumed by netzkeBulkExecute)
|
104
105
|
def invoke_endpoint(request)
|
105
106
|
component_name, *sub_components = request.cmp_path.split('__')
|
106
|
-
components_in_session = session[:netzke_components].try(:symbolize_keys)
|
107
107
|
|
108
|
-
if
|
109
|
-
cmp_config = components_in_session[component_name.to_sym].symbolize_keys
|
108
|
+
if cmp_config = config_in_session(component_name)
|
110
109
|
cmp_config[:client_config] = request.client_configs.shift || {}
|
111
110
|
component_instance = Netzke::Base.instance_by_config(cmp_config)
|
112
111
|
component_instance.invoke_endpoint((sub_components + [request.endpoint]).join("__"), request.args, request.client_configs)
|
113
112
|
else
|
114
|
-
{
|
113
|
+
{ netzke_on_session_expired: [] }
|
115
114
|
end
|
116
115
|
end
|
117
116
|
|
@@ -120,19 +119,26 @@ module Netzke
|
|
120
119
|
# E.g.: some_grid__post_grid_data.
|
121
120
|
def endpoint_dispatch(endpoint_path)
|
122
121
|
component_name, *sub_components = endpoint_path.split('__')
|
123
|
-
component_instance = Netzke::Base.instance_by_config(session[:netzke_components][component_name.to_sym])
|
124
122
|
|
125
|
-
|
126
|
-
|
127
|
-
|
123
|
+
if cmp_config = config_in_session(component_name)
|
124
|
+
cmp_config[:client_config] = ActiveSupport::JSON.decode(params[:configs]).shift || {}
|
125
|
+
component_instance = Netzke::Base.instance_by_config(cmp_config)
|
128
126
|
|
129
|
-
|
127
|
+
render text: component_instance.invoke_endpoint(sub_components.join("__"), [params]).netzke_jsonify.to_json, layout: false
|
128
|
+
else
|
129
|
+
render text: { netzke_on_session_expired: [] }.to_json, layout: false
|
130
|
+
end
|
130
131
|
end
|
131
132
|
|
132
133
|
def set_controller_and_session
|
133
134
|
Netzke::Base.controller = self
|
134
135
|
Netzke::Base.session = session
|
135
136
|
end
|
137
|
+
|
138
|
+
def config_in_session(component_name)
|
139
|
+
components_in_session = (session[:netzke_components] || {}).symbolize_keys
|
140
|
+
components_in_session[component_name.to_sym].try(:symbolize_keys)
|
141
|
+
end
|
136
142
|
end
|
137
143
|
end
|
138
144
|
end
|
data/lib/netzke/core/services.rb
CHANGED
@@ -5,7 +5,7 @@ module Netzke::Core
|
|
5
5
|
#
|
6
6
|
# An endpoint is defined through the +endpoint+ class method on the Ruby class:
|
7
7
|
#
|
8
|
-
# endpoint :do_something do
|
8
|
+
# endpoint :do_something do
|
9
9
|
# # ...
|
10
10
|
# end
|
11
11
|
#
|
@@ -14,74 +14,78 @@ module Netzke::Core
|
|
14
14
|
#
|
15
15
|
# == Calling an endpoint from JavaScript
|
16
16
|
#
|
17
|
-
# By defining the endpoint on the Ruby class, the client side automatically gets an equally named (
|
17
|
+
# By defining the endpoint on the Ruby class, the client side automatically gets an equally named (in camelCase) function that is used to call the endpoint. In the previous example, that would be +doSomething+. Its signature goes as follows:
|
18
18
|
#
|
19
|
-
# this.doSomething(
|
19
|
+
# this.server.doSomething(args..., callback, scope);
|
20
20
|
#
|
21
|
-
# * +
|
22
|
-
# * +
|
23
|
-
# * +scope+ (optional) the scope in which +
|
21
|
+
# * +args+ (optional) is what the +endpoint+ block at the server will receive as parameters
|
22
|
+
# * +callback+ (optional) will be called after the server successfully processes the request
|
23
|
+
# * +scope+ (optional) the scope in which +callback+ will be called, defaults to component instance
|
24
24
|
#
|
25
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
26
|
#
|
27
27
|
# == Envoking JavaScript methods from the server
|
28
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
|
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 via the +client+ variable:
|
30
30
|
#
|
31
|
-
# endpoint :do_something do
|
31
|
+
# endpoint :do_something do
|
32
32
|
# # ... do the thing
|
33
|
-
#
|
34
|
-
#
|
33
|
+
# client.set_title("New title")
|
34
|
+
# client.add_class("some-extra-css")
|
35
35
|
# end
|
36
36
|
#
|
37
|
-
# This will result in successive calling the +setTitle+ and +addClass+ methods on the JavaScript instance of
|
37
|
+
# This will result in successive calling the +setTitle+ and +addClass+ methods on the JavaScript instance of the component.
|
38
38
|
#
|
39
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
40
|
#
|
41
|
-
# endpoint :do_something do
|
41
|
+
# endpoint :do_something do
|
42
42
|
# # ... do the thing
|
43
|
-
#
|
44
|
-
#
|
43
|
+
# client.east_panel_component.set_title("New east panel title")
|
44
|
+
# client.east_panel_component.deep_nested_component.do_something_very_special("With", "some", "arguments")
|
45
45
|
# end
|
46
46
|
#
|
47
47
|
# == Providing arguments to the callback function
|
48
48
|
#
|
49
|
-
# The callback function provided at the moment of calling an endpoint
|
49
|
+
# The callback function provided at the moment of calling an endpoint will receive as its only argument the result of
|
50
|
+
# the +endpoint+ block execution:
|
50
51
|
#
|
51
|
-
# endpoint :
|
52
|
+
# endpoint :get_the_answer do
|
52
53
|
# # ... do the thing
|
53
|
-
#
|
54
|
+
# 42
|
54
55
|
# end
|
55
56
|
#
|
56
57
|
# By calling the endpoint from the client side like this:
|
57
58
|
#
|
58
|
-
# this.
|
59
|
+
# this.server.getTheAnswer(function(result){ console.debug(result); });
|
59
60
|
#
|
60
|
-
# ... the value of +result+ after the execution
|
61
|
+
# ... the value of +result+ after the endpoint execution will be 42. Using this mechanism can be seen as doing an asyncronous call to a server-side function that returns a value.
|
61
62
|
#
|
62
63
|
# == Overriding an endpoint
|
63
64
|
#
|
64
65
|
# When overriding an endpoint, you can call the original endpoint by using +super+ and explicitely providing the block parameters to it:
|
65
66
|
#
|
66
|
-
# endpoint :do_something do |
|
67
|
-
# super(
|
68
|
-
#
|
67
|
+
# endpoint :do_something do |arg1, arg2|
|
68
|
+
# super(arg1, arg2)
|
69
|
+
# client.do_more
|
69
70
|
# end
|
70
71
|
#
|
71
|
-
# If you want to reuse the original arguments set in +super+, you can access them from the +
|
72
|
+
# If you want to reuse the original arguments set in +super+, you can access them from the +client+ object. Provided we are overriding the +do_something+ endpoint from the example in "Envoking JavaScript methods from the server", we will have:
|
72
73
|
#
|
73
|
-
# endpoint :do_something do |params
|
74
|
-
# super(params
|
75
|
-
# original_arguments_for_set_title =
|
76
|
-
# original_arguments_for_add_class =
|
74
|
+
# endpoint :do_something do |params|
|
75
|
+
# super(params)
|
76
|
+
# original_arguments_for_set_title = client.set_title # => ["New title"]
|
77
|
+
# original_arguments_for_add_class = client.add_class # => ["some-extra-css"]
|
77
78
|
# end
|
78
79
|
module Services
|
79
80
|
extend ActiveSupport::Concern
|
80
81
|
|
81
82
|
included do
|
82
|
-
|
83
|
+
# Returns all endpoints as a hash
|
83
84
|
class_attribute :endpoints
|
84
85
|
self.endpoints = {}
|
86
|
+
|
87
|
+
# instance of EndpointResponse
|
88
|
+
attr_accessor :client
|
85
89
|
end
|
86
90
|
|
87
91
|
module ClassMethods
|
@@ -99,34 +103,33 @@ module Netzke::Core
|
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
102
|
-
# Invokes an endpoint
|
106
|
+
# Invokes an endpoint
|
107
|
+
#
|
103
108
|
# +endpoint+ may contain the path to the endpoint in a component down the hierarchy, e.g.:
|
109
|
+
# +params+ contains an Array of parameters to pass to the endpoint
|
104
110
|
#
|
105
111
|
# invoke_endpoint(:users__center__get_data, params)
|
112
|
+
#
|
113
|
+
# Returns instance of EndpointResponse
|
106
114
|
def invoke_endpoint(endpoint, params, configs = [])
|
107
|
-
|
115
|
+
self.client = Netzke::Core::EndpointResponse.new
|
108
116
|
|
109
117
|
if has_endpoint?(endpoint)
|
110
|
-
send("#{endpoint}_endpoint", params
|
111
|
-
|
118
|
+
client.netzke_set_result(send("#{endpoint}_endpoint", *params))
|
119
|
+
client
|
112
120
|
else
|
113
|
-
# Let's try to find it
|
121
|
+
# Let's try to find it in a component down the tree
|
114
122
|
child_component, *action = endpoint.to_s.split('__')
|
115
|
-
|
123
|
+
|
116
124
|
action = !action.empty? && action.join("__").to_sym
|
125
|
+
return unknown_exception(:endpoint, endpoint) if !action
|
126
|
+
|
127
|
+
client_config = configs.shift || {}
|
128
|
+
child_config = component_config(child_component.to_sym, client_config: client_config)
|
117
129
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
client_config = configs.shift || {}
|
122
|
-
js_id = client_config.delete("component_id")
|
123
|
-
cmp_strong_config = {client_config: client_config, js_id: js_id}
|
124
|
-
component_instance(child_component, cmp_strong_config).invoke_endpoint(action, params, configs)
|
125
|
-
else
|
126
|
-
# component_missing can be overridden if necessary
|
127
|
-
component_missing(child_component, params, endpoint_response)
|
128
|
-
endpoint_response
|
129
|
-
end
|
130
|
+
return unknown_exception(:component, child_component) if child_config.nil?
|
131
|
+
|
132
|
+
component_instance(child_config).invoke_endpoint(action, params, configs)
|
130
133
|
end
|
131
134
|
end
|
132
135
|
|
@@ -136,9 +139,19 @@ module Netzke::Core
|
|
136
139
|
|
137
140
|
# Called when the method_missing tries to processes a non-existing component. Override when needed.
|
138
141
|
# Note: this should actually never happen unless you mess up with Netzke component loading mechanisms.
|
139
|
-
def component_missing(missing_component, params
|
140
|
-
|
142
|
+
def component_missing(missing_component, *params)
|
143
|
+
client.netzke_notify "Unknown component '#{missing_component}' in '#{name}'"
|
141
144
|
end
|
142
145
|
|
146
|
+
private
|
147
|
+
|
148
|
+
def unknown_exception(entity_name, entity)
|
149
|
+
client.netzke_set_result(error: {
|
150
|
+
type: "UNKNOWN_#{entity_name.to_s.upcase}",
|
151
|
+
msg: "Component '#{self.class.name}' does not have #{entity_name} '#{entity}'"
|
152
|
+
})
|
153
|
+
|
154
|
+
client
|
155
|
+
end
|
143
156
|
end
|
144
157
|
end
|
data/lib/netzke/core/session.rb
CHANGED
@@ -7,8 +7,6 @@ module Netzke::Core
|
|
7
7
|
@component_id = component_id.to_s
|
8
8
|
Netzke::Base.session ||= {}
|
9
9
|
Netzke::Base.session[:netzke_sessions] ||= {}
|
10
|
-
# @session = Netzke::Base.session[:netzke_sessions][@component_id] ||= {}
|
11
|
-
# @session = {}
|
12
10
|
end
|
13
11
|
|
14
12
|
# Delegate everything to session
|