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.
- data/.travis.yml +1 -2
- data/CHANGELOG.md +572 -0
- data/LICENSE +7 -1
- data/README.md +345 -29
- data/Rakefile +3 -3
- data/app/controllers/netzke_controller.rb +37 -48
- data/config/ci/before-travis.sh +3 -4
- data/javascripts/base.js +86 -150
- data/javascripts/ext.js +180 -210
- data/javascripts/{core_extensions.js → js_extensions.js} +0 -0
- data/lib/netzke-core.rb +16 -6
- data/lib/netzke/base.rb +84 -107
- data/lib/netzke/core.rb +7 -41
- data/lib/netzke/core/action_config.rb +37 -0
- data/lib/netzke/core/actions.rb +123 -0
- data/lib/netzke/core/client_class.rb +252 -0
- data/lib/netzke/core/component_config.rb +12 -0
- data/lib/netzke/core/composition.rb +274 -0
- data/lib/netzke/core/config_to_dsl_delegator.rb +69 -0
- data/lib/netzke/core/configuration.rb +63 -0
- data/lib/netzke/core/css_config.rb +51 -0
- data/lib/netzke/core/dynamic_assets.rb +19 -49
- data/lib/netzke/{embedding.rb → core/embedding.rb} +4 -6
- data/lib/netzke/core/endpoint_response.rb +15 -0
- data/lib/netzke/core/javascript.rb +111 -0
- data/lib/netzke/core/panel.rb +11 -0
- data/lib/netzke/{plugins.rb → core/plugins.rb} +10 -5
- data/lib/netzke/core/railz.rb +4 -0
- data/lib/netzke/{railz → core/railz}/action_view_ext.rb +22 -18
- data/lib/netzke/core/railz/action_view_ext/ext.rb +49 -0
- data/lib/netzke/core/railz/controller_extensions.rb +17 -0
- data/lib/netzke/core/railz/engine.rb +16 -0
- data/lib/netzke/core/railz/routes.rb +10 -0
- data/lib/netzke/core/ruby_ext.rb +5 -0
- data/lib/netzke/core/ruby_ext/array.rb +23 -0
- data/lib/netzke/core/ruby_ext/hash.rb +47 -0
- data/lib/netzke/{core_ext → core/ruby_ext}/string.rb +2 -7
- data/lib/netzke/core/ruby_ext/symbol.rb +13 -0
- data/lib/netzke/{core_ext → core/ruby_ext}/time_with_zone.rb +0 -0
- data/lib/netzke/core/services.rb +130 -0
- data/lib/netzke/core/session.rb +15 -19
- data/lib/netzke/core/state.rb +40 -0
- data/lib/netzke/core/stylesheets.rb +48 -0
- data/lib/netzke/core/version.rb +2 -2
- data/lib/netzke/plugin.rb +8 -11
- data/netzke-core.gemspec +69 -59
- data/test/core_test_app/Gemfile +2 -20
- data/test/core_test_app/Gemfile.lock +65 -74
- data/test/core_test_app/app/components/card_component_loader.rb +4 -4
- data/test/core_test_app/app/components/component_loader.rb +40 -120
- data/test/core_test_app/app/components/component_loader/javascripts/component_loader.js +49 -0
- data/test/core_test_app/app/components/component_with_actions.rb +61 -47
- data/test/core_test_app/app/components/component_with_custom_css.rb +8 -5
- data/test/core_test_app/app/components/component_with_js_mixin.rb +11 -5
- data/test/core_test_app/app/components/component_with_js_mixin/javascripts/extra_one.js +1 -1
- data/test/core_test_app/app/components/component_with_js_mixin/javascripts/extra_two.js +1 -1
- data/test/core_test_app/app/components/component_with_js_mixin/javascripts/method_set_one.js +1 -1
- data/test/core_test_app/app/components/component_with_nested_through.rb +2 -2
- data/test/core_test_app/app/components/component_with_prebuilt_toolbar_control.rb +12 -0
- data/test/core_test_app/app/components/component_with_prebuilt_toolbar_control/javascripts/component_with_prebuilt_toolbar_control.js +12 -0
- data/test/core_test_app/app/components/component_with_required_js.rb +24 -0
- data/test/core_test_app/app/components/configurable_on_class_level.rb +8 -0
- data/test/core_test_app/app/components/dsl_delegated_properties.rb +4 -0
- data/test/core_test_app/app/components/dsl_delegated_properties_base.rb +5 -0
- data/test/core_test_app/app/components/dynamic_tab_panel/javascripts/dynamic_tab_panel.js +2 -2
- data/test/core_test_app/app/components/ext_direct/composite.rb +32 -33
- data/test/core_test_app/app/components/ext_direct/details.rb +2 -4
- data/test/core_test_app/app/components/ext_direct/selector.rb +20 -22
- data/test/core_test_app/app/components/ext_direct/statistics.rb +2 -4
- data/test/core_test_app/app/components/extended_component_with_actions.rb +7 -3
- data/test/core_test_app/app/components/extended_component_with_js_mixin.rb +7 -4
- data/test/core_test_app/app/components/extended_component_with_js_mixin/javascripts/some_method_set.js +1 -1
- data/test/core_test_app/app/components/extended_server_caller.rb +20 -14
- data/test/core_test_app/app/components/hello_world.rb +23 -0
- data/test/core_test_app/app/components/hello_world/javascripts/hello_world.js +12 -0
- data/test/core_test_app/app/components/included.js +2 -2
- data/test/core_test_app/app/components/kinda_complex_component.rb +1 -3
- data/test/core_test_app/app/components/kinda_complex_component/basic_stuff.rb +15 -17
- data/test/core_test_app/app/components/kinda_complex_component/extra_stuff.rb +4 -5
- data/test/core_test_app/app/components/loader_of_component_with_custom_css.rb +14 -5
- data/test/core_test_app/app/components/localized_panel.rb +23 -25
- data/test/core_test_app/app/components/multipane_component_loader.rb +19 -20
- data/test/core_test_app/app/components/nested_component.rb +4 -5
- data/test/core_test_app/app/components/panel_with_plugin.rb +8 -3
- data/test/core_test_app/app/components/panel_with_tools.rb +15 -14
- data/test/core_test_app/app/components/plugin_with_components.rb +20 -12
- data/test/core_test_app/app/components/scoped_components/deep_scoped_components/some_deep_scoped_component.rb +5 -2
- data/test/core_test_app/app/components/scoped_components/extended_scoped_component.rb +5 -2
- data/test/core_test_app/app/components/scoped_components/some_scoped_component.rb +5 -2
- data/test/core_test_app/app/components/server_caller.rb +39 -17
- data/test/core_test_app/app/components/server_caller/javascripts/server_caller.js +42 -0
- data/test/core_test_app/app/components/server_counter.rb +18 -82
- data/test/core_test_app/app/components/server_counter/javascripts/server_counter.js +53 -0
- data/test/core_test_app/app/components/simple_authentication_component.rb +46 -0
- data/test/core_test_app/app/components/simple_component.rb +8 -3
- data/test/core_test_app/app/components/simple_composite.rb +12 -0
- data/test/core_test_app/app/components/simple_form_with_file_upload.rb +49 -0
- data/test/core_test_app/app/components/simple_panel.rb +2 -2
- data/test/core_test_app/app/components/simple_tab_panel.rb +24 -3
- data/test/core_test_app/app/components/simple_window.rb +4 -2
- data/test/core_test_app/app/components/some_composite.rb +77 -48
- data/test/core_test_app/app/components/some_plugin.rb +31 -30
- data/test/core_test_app/app/components/stateful_component.rb +46 -0
- data/test/core_test_app/app/components/stateful_component_with_shared_state.rb +11 -0
- data/test/core_test_app/app/components/window_with_simple_component.rb +14 -0
- data/test/core_test_app/app/views/layouts/application.html.erb +1 -1
- data/test/core_test_app/app/views/simple_rails/multiple_nested.html.erb +7 -19
- data/test/core_test_app/app/views/simple_rails/panel.html.erb +1 -0
- data/test/core_test_app/config/database.yml.travis +3 -5
- data/test/core_test_app/config/environments/production.rb +1 -1
- data/test/core_test_app/config/initializers/netzke.rb +3 -1
- data/test/core_test_app/config/locales/en.yml +9 -4
- data/test/core_test_app/config/locales/es.yml +4 -2
- data/test/core_test_app/config/routes.rb +2 -8
- data/test/core_test_app/db/schema.rb +3 -11
- data/test/core_test_app/features/actions_and_tools.feature +1 -0
- data/test/core_test_app/features/client-server.feature +7 -0
- data/test/core_test_app/features/component_loader.feature +13 -13
- data/test/core_test_app/features/composition.feature +14 -0
- data/test/core_test_app/features/config_to_dsl_delegation.feature +10 -0
- data/test/core_test_app/features/file_inclusion.feature +1 -1
- data/test/core_test_app/features/i18n.feature +4 -4
- data/test/core_test_app/features/js_include.feature +1 -1
- data/test/core_test_app/features/persistence.feature +21 -5
- data/test/core_test_app/features/step_definitions/generic_steps.rb +14 -0
- data/test/core_test_app/features/support/paths.rb +0 -3
- data/test/core_test_app/public/images/icons/accept.png +0 -0
- data/test/core_test_app/public/images/icons/anchor.png +0 -0
- data/test/core_test_app/public/images/icons/tick.png +0 -0
- data/test/core_test_app/spec/action_config_spec.rb +15 -0
- data/test/core_test_app/spec/{component/actions_spec.rb → actions_spec.rb} +38 -36
- data/test/core_test_app/spec/base_spec.rb +35 -0
- data/test/core_test_app/spec/client_class_spec.rb +17 -0
- data/test/core_test_app/spec/component +0 -0
- data/test/core_test_app/spec/composition_spec.rb +118 -0
- data/test/core_test_app/spec/core_ext_spec.rb +3 -14
- data/test/core_test_app/spec/endpoint_response_spec.rb +17 -0
- data/test/core_test_app/spec/javascript_spec.rb +33 -0
- data/test/core_test_app/spec/js_class_config_scope.rb +37 -0
- data/test/core_test_app/spec/panel_spec.rb +11 -0
- data/test/core_test_app/spec/services_spec.rb +16 -0
- data/test/core_test_app/spec/state_spec.rb +20 -0
- data/test/unit/core_ext_test.rb +0 -53
- data/test/unit/netzke_core_test.rb +11 -11
- metadata +76 -62
- data/CHANGELOG.rdoc +0 -325
- data/javascripts/touch.js +0 -58
- data/lib/netzke/actions.rb +0 -107
- data/lib/netzke/composition.rb +0 -224
- data/lib/netzke/config_to_dsl_delegator.rb +0 -43
- data/lib/netzke/configuration.rb +0 -195
- data/lib/netzke/core/masquerading.rb +0 -34
- data/lib/netzke/core_ext.rb +0 -6
- data/lib/netzke/core_ext/array.rb +0 -30
- data/lib/netzke/core_ext/hash.rb +0 -86
- data/lib/netzke/core_ext/symbol.rb +0 -21
- data/lib/netzke/ext_component.rb +0 -25
- data/lib/netzke/inheritance.rb +0 -31
- data/lib/netzke/javascript.rb +0 -382
- data/lib/netzke/javascript/scopes.rb +0 -39
- data/lib/netzke/railz.rb +0 -4
- data/lib/netzke/railz/action_view_ext/ext.rb +0 -64
- data/lib/netzke/railz/action_view_ext/touch.rb +0 -52
- data/lib/netzke/railz/controller_extensions.rb +0 -33
- data/lib/netzke/railz/engine.rb +0 -48
- data/lib/netzke/railz/routes.rb +0 -7
- data/lib/netzke/services.rb +0 -101
- data/lib/netzke/session.rb +0 -54
- data/lib/netzke/state.rb +0 -91
- data/lib/netzke/stylesheets.rb +0 -65
- data/test/core_test_app/app/components/component_with_included_js.rb +0 -16
- data/test/core_test_app/app/components/component_with_session_persistence.rb +0 -35
- data/test/core_test_app/app/components/deprecated/server_caller.rb +0 -20
- data/test/core_test_app/app/components/dynamic_tab_panel.rb +0 -19
- data/test/core_test_app/app/components/hello_world_component.rb +0 -31
- data/test/core_test_app/app/components/touch/hello_world_component.rb +0 -25
- data/test/core_test_app/app/components/touch/server_caller.rb +0 -28
- data/test/core_test_app/app/components/touch/simple_carousel.rb +0 -17
- data/test/core_test_app/app/controllers/touch_controller.rb +0 -6
- data/test/core_test_app/app/helpers/touch_helper.rb +0 -2
- data/test/core_test_app/app/views/layouts/touch.html.erb +0 -13
- data/test/core_test_app/db/migrate/20110110132720_create_netzke_component_states.rb +0 -20
- data/test/core_test_app/features/step_definitions/touch_steps.rb +0 -3
- data/test/core_test_app/features/touch.feature +0 -10
- data/test/core_test_app/gemfiles/rails3_1.gemfile +0 -16
- data/test/core_test_app/gemfiles/rails3_2.gemfile +0 -16
- data/test/core_test_app/spec/component/base_spec.rb +0 -36
- data/test/core_test_app/spec/component/component_spec.rb +0 -20
- data/test/core_test_app/spec/component/composition_spec.rb +0 -132
- data/test/core_test_app/spec/component/configuration_spec.rb +0 -61
- data/test/core_test_app/spec/component/javascript_spec.rb +0 -16
- data/test/core_test_app/spec/component/state_spec.rb +0 -18
data/LICENSE
CHANGED
@@ -1 +1,7 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2012 netzke
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,54 +1,370 @@
|
|
1
|
-
# Netzke Core
|
1
|
+
# Netzke Core [![Build Status](https://secure.travis-ci.org/nomadcoder/netzke-core.png?branch=master)](http://travis-ci.org/nomadcoder/netzke-core) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/netzke/netzke-core)
|
2
2
|
|
3
|
-
[
|
3
|
+
[RDocs](http://rdoc.info/projects/netzke/netzke-core)
|
4
4
|
|
5
|
-
Netzke Core is the bare bones of the [Netzke framework](
|
5
|
+
Netzke Core is the bare bones of the [Netzke framework](http://netzke.org). For pre-built full-featured components (like grids, forms, tab/accordion panels, etc), see [netzke-basepack](http://github.com/netzke/netzke-basepack) and [netzke-communitypack](http://github.com/netzke/netzke-communitypack).
|
6
|
+
|
7
|
+
Some knowledge of Sencha Ext JS will be needed in order to fully understand this overview.
|
8
|
+
|
9
|
+
## Rationale
|
10
|
+
|
11
|
+
[Sencha Ext JS]("http://www.sencha.com/products/extjs") is a powerful front-end framework, which is used for crafting web-apps that give the end user experience similar to that of a desktop application. It has an extensive set of widgets ('components'), and leverages a modular approach to its fullest: a developer can extend components (using Ext JS's own [class system]("http://docs.sencha.com/ext-js/4-1/#!/guide/class_system")), nest components using many powerful layouts, dynamically create and destroy them. The architecture of Ext JS is well-thought and very complete.
|
12
|
+
|
13
|
+
However, with Ext JS being server-agnostic, it is not always a trivial task for a developer to bind Ext JS components to the server-side data *and* application business logic, especially in complex applications. Netzke as the solution that allows you to extend the modular approach to the server side.
|
6
14
|
|
7
15
|
Netzke Core takes the burden of implementing the following key aspects of the framework:
|
8
16
|
|
9
|
-
* JavaScript class generation
|
17
|
+
* Client-side (JavaScript) class generation
|
10
18
|
* Client-server communication
|
11
|
-
*
|
19
|
+
* Convenient declaration of Ext actions
|
20
|
+
* Extendibility of components (class inheritance and mixins)
|
12
21
|
* Unlimited nesting (composition)
|
13
22
|
* Dynamic component loading
|
14
|
-
*
|
15
|
-
* Inclusion of
|
16
|
-
|
23
|
+
* Client-side class caching
|
24
|
+
* Inclusion of extra JavaScript and CSS files
|
25
|
+
|
26
|
+
...and more.
|
27
|
+
|
28
|
+
All this extremely facilitates building fast, low-traffic, robust, and highly maintainable applications. As a result, your code scales much better in the sense of complexity, compared to using conventional MVC, where developers are pretty much limited with programming techniques they can apply.
|
29
|
+
|
30
|
+
## HelloWorld component
|
31
|
+
|
32
|
+
*This component is distributed as a part of the test application, see `test/core_test_app/components`.*
|
33
|
+
|
34
|
+
In `YOUR_APP/components/hello_world.rb`:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class HelloWorld < Netzke::Base
|
38
|
+
# Configure client class
|
39
|
+
js_configure do |c|
|
40
|
+
c.title = "Hello World component"
|
41
|
+
c.mixin # mix in methods from hello_world/javascripts/hello_world.js
|
42
|
+
end
|
43
|
+
|
44
|
+
# Actions are used by Ext JS to share functionality and state b/w buttons and menu items
|
45
|
+
# The handler for this action should be called onPingServer by default
|
46
|
+
action :ping_server
|
47
|
+
|
48
|
+
# Self-configure with a bottom toolbar
|
49
|
+
def configure(c)
|
50
|
+
super
|
51
|
+
c.bbar = [:ping_server] # embed the action into bottom toolbar as a button
|
52
|
+
end
|
53
|
+
|
54
|
+
# Endpoint callable from client class
|
55
|
+
endpoint :greet_the_world do |params,this|
|
56
|
+
# call client class' method showGreeting
|
57
|
+
this.show_greeting("Hello World!")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
In `YOUR_APP/components/hello_world/javascripts/hello_world.js` put the client class (JavaScript) methods:
|
63
|
+
|
64
|
+
```javascript
|
65
|
+
{
|
66
|
+
// handler for the ping_server action
|
67
|
+
onPingServer: function(){
|
68
|
+
// calling greet_the_world endpoint
|
69
|
+
this.greetTheWorld();
|
70
|
+
},
|
71
|
+
|
72
|
+
// called by the server as the result of executing the endpoint
|
73
|
+
showGreeting: function(greeting){
|
74
|
+
this.update("Server says: " + greeting);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
```
|
78
|
+
|
79
|
+
To embed the component in Rails view:
|
80
|
+
|
81
|
+
Add `netzke` routes:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# in routes.rb
|
85
|
+
RailsApp::Application.routes.draw do
|
86
|
+
netzke
|
87
|
+
...
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
Use `load_netzke` in the layout to include Ext JS and Netzke scripts and stylesheets:
|
92
|
+
|
93
|
+
```erb
|
94
|
+
<!DOCTYPE html>
|
95
|
+
<html>
|
96
|
+
<head>
|
97
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
98
|
+
<%= csrf_meta_tag %>
|
99
|
+
<%= load_netzke %>
|
100
|
+
</head>
|
101
|
+
<body>
|
102
|
+
<%= yield %>
|
103
|
+
</body>
|
104
|
+
</html>
|
105
|
+
```
|
106
|
+
|
107
|
+
Embed the component in the Rails view:
|
108
|
+
|
109
|
+
```erb
|
110
|
+
<%= netzke :hello_world %>
|
111
|
+
```
|
112
|
+
|
113
|
+
## What is a Netzke component
|
114
|
+
|
115
|
+
A Netzke component is a Ruby class (further referred to as "server class"), which is being represented by an Ext JS Component on the server-side (further referred to as "client class"). The responsibility of the server class is to "assemble" the client class and provide the configuration for its instance (further referred as "client class instance"). Even if it may sound a bit complicated, Netzke provides a simple API for defining and configuring the client class. See [Client class](#client-class) for details.
|
116
|
+
|
117
|
+
Further, each Netzke component inherits convenient API for enabling the communication between the client and server class. See [Client-server interaction](#client-server-interaction) for details.
|
118
|
+
|
119
|
+
With Netzke components being a Ruby class, and the client class being *incapsulated* in it, it is possible to use a Netzke component in your application by simply writing Ruby code. However, while creating a component, developers can fully use their Ext JS skills - Netzke puts no obstacles here.
|
120
|
+
|
121
|
+
A typical Netzke component's code is structured like this (on example of MyComponent):
|
122
|
+
|
123
|
+
```
|
124
|
+
your_web_app
|
125
|
+
app
|
126
|
+
components
|
127
|
+
my_component.rb <-- the Ruby class
|
128
|
+
my_component
|
129
|
+
some_module.rb <-- optional extra Ruby code
|
130
|
+
javascripts
|
131
|
+
some_dependency.js <-- optional external JS library
|
132
|
+
init_component.js <-- optional mixins to the client class
|
133
|
+
extra_functionality.js <-- more mixins (mixin-in may depend on component class configuration)
|
134
|
+
stylesheets
|
135
|
+
my_special_button.css <-- optional custom CSS
|
136
|
+
```
|
137
|
+
|
138
|
+
## Client class
|
139
|
+
|
140
|
+
The generated client class is *inherited* (as defined by the Ext JS [class system]("http://docs.sencha.com/ext-js/4-1/#!/guide/class_system")) from an Ext JS class, which by default is [Ext.panel.Panel]("http://docs.sencha.com/ext-js/4-1/#!/api/Ext.panel.Panel"). For example, a component defined like this:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
class HelloWorld < Netzke::Base
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
will have the following client class generated by Netzke (simplified):
|
148
|
+
|
149
|
+
```javascript
|
150
|
+
Ext.define('Netzke.classes.HelloWorld', {"extend":"Ext.panel.Panel", "mixins":["Netzke.classes.Core.Mixin"]});
|
151
|
+
```
|
152
|
+
|
153
|
+
`Netzke.classes.Core.Mixin` contains a set of client class methods and properties common to every Netzke component.
|
154
|
+
|
155
|
+
Extending `HelloWorld` will be automatically reflected on the client-class level:
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
class HelloNewWorld < HelloWorld
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
will have the following client class generated (simplified):
|
163
|
+
|
164
|
+
```javascript
|
165
|
+
Ext.define('Netzke.classes.HelloNewWorld', {"extend":"Netzke.classes.HelloWorld"});
|
166
|
+
```
|
167
|
+
|
168
|
+
The configuration of a client-class is done by using the `Netzke::Base.js_configure`. For example, in order to inherit from a different Ext JS component, and to mix in the methods defined in an external JavaScript class:
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
class MyTabPanel < Netzke::Base
|
172
|
+
js_configure do |c|
|
173
|
+
c.extend = "Ext.tab.Panel"
|
174
|
+
c.mixin :extra_functionality
|
175
|
+
end
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
For more details on defining the client class, refer to [Netzke::Core::ClientClass](http://rdoc.info/github/netzke/netzke-core/Netzke/Core/ClientClass).
|
180
|
+
|
181
|
+
## Composition
|
182
|
+
|
183
|
+
Any Netzke component can define child components, which can either be statically nested in the compound layout (e.g. as different regions of the ['border' layout]("http://docs.sencha.com/ext-js/4-1/#!/api/Ext.layout.container.Border")), or dynamically loaded at a request (as in the case of the edit form window in `Netzke::Basepack::GridPanel`, for example).
|
184
|
+
|
185
|
+
### Defining child components
|
186
|
+
|
187
|
+
You can define a child component by calling the `component` class method which normally requires a block:
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
component :users do |c|
|
191
|
+
c.klass = GridPanel
|
192
|
+
c.model = "User"
|
193
|
+
c.title = "Users"
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
### Nesting components
|
198
|
+
|
199
|
+
Declared components can be referred to in the component layout:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
def configure(c)
|
203
|
+
super
|
204
|
+
c.items = [
|
205
|
+
{ xtype: :panel, title: "Simple Ext panel" },
|
206
|
+
:users
|
207
|
+
]
|
208
|
+
end
|
209
|
+
```
|
210
|
+
|
211
|
+
### Dynamic loading of components
|
212
|
+
|
213
|
+
Next to being statically nested in the layout, a child component can also be dynamically loaded by using client class' `netzkeLoadComponent` method:
|
17
214
|
|
18
|
-
|
215
|
+
this.netzkeLoadComponent('users');
|
216
|
+
|
217
|
+
this will load the "users" component and [add](http://docs.sencha.com/ext-js/4-1/#!/api/Ext.container.Container-method-add) it to the current container.
|
218
|
+
|
219
|
+
For more details on dynamic component loading refer to inline docs of [javascript/ext.js](https://github.com/netzke/netzke-core/blob/master/javascripts/ext.js).
|
220
|
+
|
221
|
+
For more details on composition refer to [Netzke::Core::Composition](http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Composition).
|
222
|
+
|
223
|
+
## Actions, toolbars, and menus
|
224
|
+
|
225
|
+
Actions are [used by Ext JS]("http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Action") to share functionality and state among multiple buttons and menu items. Define actions with the `action` class method:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
action :show_report do |c|
|
229
|
+
c.text = "Show report"
|
230
|
+
c.icon = :report
|
231
|
+
end
|
232
|
+
```
|
233
|
+
|
234
|
+
The icon for this button will be `images/icons/report.png` (see [Icons support](#icons-support)).
|
235
|
+
|
236
|
+
Refer to actions in toolbars:
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
def configure(c)
|
240
|
+
super
|
241
|
+
c.bbar = [:show_report]
|
242
|
+
end
|
243
|
+
```
|
244
|
+
|
245
|
+
Actions can also be referred to is submenus:
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
c.tbar = [{text: 'Menu', menu: {items: [:show_report]}}]
|
249
|
+
```
|
250
|
+
|
251
|
+
For more details on composition refer to [Netzke::Core::Action](http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Action).
|
252
|
+
|
253
|
+
## Client-server interaction
|
254
|
+
|
255
|
+
Communication between the client class and the corresponding server class is done by means of defining *endpoints*. By defining an endpoint on the server, the client class automatically gets a method that is used to call the server.
|
256
|
+
|
257
|
+
### Calling an endpoint from client class
|
258
|
+
|
259
|
+
By defining an endpoint like this:
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
class SimpleComponent < Netzke::Base
|
263
|
+
endpoint :whats_up_server do |params, this|
|
264
|
+
# ...
|
265
|
+
end
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
...the client class will obtain a method called `whatsUpServer`:
|
270
|
+
|
271
|
+
```javascript
|
272
|
+
this.whatsUpServer(params, callback, scope);
|
273
|
+
```
|
274
|
+
|
275
|
+
Parameters:
|
276
|
+
|
277
|
+
* `params` will be passed to the endpoint block as the first parameter
|
278
|
+
* `callback` (optional) receives a function to be called after the server successfully processes the endpoint call
|
279
|
+
* `scope` (optional) is the scope in which the callback function will be called
|
280
|
+
|
281
|
+
### Calling client class methods from endpoint
|
282
|
+
|
283
|
+
An endpoint can instruct the client class to execute a set of methods after its execution, passing those methods arbitrary parameters. For example:
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
class SimpleComponent < Netzke::Base
|
287
|
+
endpoint :whats_up_server do |params, this|
|
288
|
+
this.set_title("All quiet here on the server")
|
289
|
+
this.my_method
|
290
|
+
end
|
291
|
+
end
|
292
|
+
```
|
293
|
+
|
294
|
+
Here the client class will call its `setTitle` method (defined in `Ext.panel.Panel`) with parameter passed from the endpoint. Then a custom method `myMethod` will be called with no parameters.
|
295
|
+
|
296
|
+
For more details on client-server communication see [Netzke::Core::Services]("http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Services").
|
297
|
+
|
298
|
+
## Icons support
|
299
|
+
|
300
|
+
Netzke can optionally make use of icons for making clickable elements like buttons and menu items more visual. The icons should be (by default) located in `public/images/icons`.
|
301
|
+
|
302
|
+
An example of specifying an icon for an action:
|
303
|
+
|
304
|
+
```ruby
|
305
|
+
action :logout do |c|
|
306
|
+
c.icon = :door
|
307
|
+
end
|
308
|
+
```
|
309
|
+
|
310
|
+
The logout action will be configured with `public/images/icons/door.png` as icon.
|
311
|
+
|
312
|
+
For more details on using icons refer to [Netzke::Core::Actions]("http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Actions").
|
313
|
+
|
314
|
+
## I18n
|
315
|
+
|
316
|
+
Netzke Core will automatically include Ext JS localization files based on current `I18n.locale`.
|
317
|
+
|
318
|
+
Also, Netzke Core uses some conventions for localizing actions. Refer to [Netzke::Core::Actions](http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Actions).
|
19
319
|
|
20
320
|
## Requirements
|
21
321
|
|
22
322
|
* Ruby ~> 1.9.2
|
23
|
-
* Rails ~> 3.
|
323
|
+
* Rails ~> 3.2.0
|
24
324
|
* Ext JS ~> 4.1.0
|
25
325
|
|
26
|
-
##
|
326
|
+
## Installation
|
327
|
+
|
328
|
+
$ gem install netzke-core
|
329
|
+
|
330
|
+
For the latest ("edge") stuff, instruct the bundler to get the gem straight from github:
|
331
|
+
|
332
|
+
```ruby
|
333
|
+
gem 'netzke-core', git: "git://github.com/netzke/netzke-core.git"
|
334
|
+
```
|
27
335
|
|
28
|
-
|
29
|
-
* Learn how to build the [Hello World!](https://github.com/nomadcoder/netzke-core/wiki/Hello-world-extjs) component.
|
30
|
-
* Dive into the [documentation](https://github.com/nomadcoder/netzke/wiki).
|
31
|
-
* Get help on the [Google Groups](http://groups.google.com/group/netzke).
|
336
|
+
By default, Netzke assumes that your Ext JS library is located in public/extjs. It can be a symbolic link, e.g.:
|
32
337
|
|
33
|
-
|
338
|
+
$ ln -s ~/code/sencha/ext-4.1.1 public/extjs
|
34
339
|
|
35
|
-
|
340
|
+
*(Make sure that the location of the license.txt distributed with Ext JS is exactly `public/extjs/license.txt`)*
|
36
341
|
|
37
|
-
|
342
|
+
## Running tests
|
343
|
+
|
344
|
+
The bundled `test/core_test_app` application used for automated testing can be easily run as a stand-alone Rails app. It's a good source of concise, focused examples. After starting the application, access any of the test components (located in `app/components`) by using the following url:
|
345
|
+
|
346
|
+
http://localhost:3000/components/{name of the component's class}
|
347
|
+
|
348
|
+
For example [http://localhost:3000/components/ServerCaller](http://localhost:3000/components/ServerCaller)
|
349
|
+
|
350
|
+
Before being able run the test app and the tests themselves, you must link your Ext JS library to `test/core_test_app/public`, e.g. (from the gems's root):
|
351
|
+
|
352
|
+
$ ln -s ~/code/sencha/ext-4.1.1 test/core_test_app/public/extjs
|
353
|
+
|
354
|
+
For cucumber tests (from `test/core_test_app`):
|
355
|
+
|
356
|
+
$ cucumber features
|
357
|
+
|
358
|
+
For RSpec tests (from `test/core_test_app`):
|
359
|
+
|
360
|
+
$ rspec spec
|
38
361
|
|
39
362
|
## Useful links
|
40
363
|
* [Project website](http://netzke.org)
|
41
|
-
* [
|
42
|
-
* [Live-demo](http://demo.netzke.org) (features [Netzke Basepack](https://github.com/nomadcoder/netzke-basepack), with sample code)
|
364
|
+
* [Live demo](http://netzke-demo.herokuapp.com) (features [Netzke Basepack](https://github.com/netzke/netzke-basepack), with sample code)
|
43
365
|
* [Twitter](http://twitter.com/netzke) - latest news about the framework
|
44
|
-
* [Author's twitter](http://twitter.com/nomadcoder) - author's rambling about OS X, productivity, lifestyle, and what not
|
45
|
-
|
46
|
-
## Ext 3 support
|
47
|
-
Versions 0.6.x are for you if you're using Ext 3 (*hardly maintained*)
|
48
|
-
|
49
|
-
## Rails 2 support
|
50
|
-
With Rails 2 (and Ext 3 only), use versions 0.5.x (*not maintained*)
|
51
366
|
|
52
367
|
---
|
53
|
-
Copyright (c) 2008-
|
54
|
-
|
368
|
+
Copyright (c) 2008-2012 [netzke](https://twitter.com/netzke), released under the MIT license (see LICENSE).
|
369
|
+
|
370
|
+
**Note** that Ext JS is licensed [differently](http://www.sencha.com/products/extjs/license/), and you may need to purchase a commercial license in order to use it in your projects!
|
data/Rakefile
CHANGED
@@ -4,8 +4,8 @@ begin
|
|
4
4
|
Jeweler::Tasks.new do |gemspec|
|
5
5
|
gemspec.version = Netzke::Core::Version::STRING
|
6
6
|
gemspec.name = "netzke-core"
|
7
|
-
gemspec.summary = "
|
8
|
-
gemspec.description = "Allows building
|
7
|
+
gemspec.summary = "Client-server GUI components with Sencha Ext JS and Ruby"
|
8
|
+
gemspec.description = "Allows building complex RIA by greatly facilitating modular development"
|
9
9
|
gemspec.email = "nmcoder@gmail.com"
|
10
10
|
gemspec.homepage = "http://netzke.org"
|
11
11
|
gemspec.authors = ["nomadcoder"]
|
@@ -31,7 +31,7 @@ begin
|
|
31
31
|
end
|
32
32
|
|
33
33
|
namespace :yard do
|
34
|
-
desc "Publish docs"
|
34
|
+
desc "Publish docs to api.netzke.org"
|
35
35
|
task publish: :yard do
|
36
36
|
dir = 'www/api.netzke.org/core'
|
37
37
|
puts "Publishing to fl:#{dir}..."
|
@@ -1,5 +1,4 @@
|
|
1
1
|
class NetzkeController < ApplicationController
|
2
|
-
|
3
2
|
# Action for Ext.Direct RPC calls
|
4
3
|
def direct
|
5
4
|
result=""
|
@@ -10,9 +9,9 @@ class NetzkeController < ApplicationController
|
|
10
9
|
begin
|
11
10
|
result += invoke_endpoint(batch[:act], batch[:method].underscore, batch[:data].first, batch[:tid])
|
12
11
|
rescue Exception => e
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
logger.error "!!! Netzke: Error invoking endpoint: #{batch[:act]} #{batch[:method].underscore} #{batch[:data].inspect} #{batch[:tid]}\n"
|
13
|
+
logger.error e.message
|
14
|
+
logger.error e.backtrace.join("\n")
|
16
15
|
error=true
|
17
16
|
break;
|
18
17
|
end
|
@@ -24,12 +23,7 @@ class NetzkeController < ApplicationController
|
|
24
23
|
render :text => result, :layout => false, :status => error ? 500 : 200
|
25
24
|
end
|
26
25
|
|
27
|
-
#
|
28
|
-
def dispatcher
|
29
|
-
endpoint_dispatch(params[:address])
|
30
|
-
end
|
31
|
-
|
32
|
-
# Used in development mode for on-the-fly generation of public/netzke/ext.[js|css]
|
26
|
+
# On-the-fly generation of public/netzke/ext.[js|css]
|
33
27
|
def ext
|
34
28
|
respond_to do |format|
|
35
29
|
format.js {
|
@@ -42,51 +36,46 @@ class NetzkeController < ApplicationController
|
|
42
36
|
end
|
43
37
|
end
|
44
38
|
|
45
|
-
#
|
46
|
-
def
|
47
|
-
|
48
|
-
format.js {
|
49
|
-
render :text => Netzke::Core::DynamicAssets.touch_js
|
50
|
-
}
|
51
|
-
|
52
|
-
format.css {
|
53
|
-
render :text => Netzke::Core::DynamicAssets.touch_css
|
54
|
-
}
|
55
|
-
end
|
39
|
+
# Old-way action used at multi-part form submission (endpointUrl)
|
40
|
+
def dispatcher
|
41
|
+
endpoint_dispatch(params[:address])
|
56
42
|
end
|
57
43
|
|
58
|
-
|
59
|
-
def invoke_endpoint(endpoint_path, action, params, tid) #:nodoc:
|
60
|
-
component_name, *sub_components = endpoint_path.split('__')
|
61
|
-
components_in_session = Netzke::Core.session[:netzke_components]
|
44
|
+
protected
|
62
45
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
else
|
67
|
-
result = {:component_not_in_session => true}.to_nifty_json
|
68
|
-
end
|
46
|
+
def invoke_endpoint(endpoint_path, action, params, tid)
|
47
|
+
component_name, *sub_components = endpoint_path.split('__')
|
48
|
+
components_in_session = session[:netzke_components]
|
69
49
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
:result => result.present? && result.l || {}
|
76
|
-
}.to_json
|
50
|
+
if components_in_session
|
51
|
+
component_instance = Netzke::Base.instance_by_config(components_in_session[component_name.to_sym])
|
52
|
+
result = component_instance.invoke_endpoint((sub_components + [action]).join("__"), params).to_nifty_json
|
53
|
+
else
|
54
|
+
result = {:netzke_component_not_in_session => true}.to_nifty_json
|
77
55
|
end
|
78
56
|
|
79
|
-
#
|
80
|
-
|
81
|
-
# E.g.: some_grid__post_grid_data.
|
82
|
-
def endpoint_dispatch(endpoint_path)
|
83
|
-
component_name, *sub_components = endpoint_path.split('__')
|
84
|
-
component_instance = Netzke::Base.instance_by_config(Netzke::Core.session[:netzke_components][component_name.to_sym])
|
57
|
+
# We render text/plain, so that the browser never modifies our response
|
58
|
+
response.headers["Content-Type"] = "text/plain; charset=utf-8"
|
85
59
|
|
86
|
-
|
87
|
-
|
60
|
+
{ :type => "rpc",
|
61
|
+
:tid => tid,
|
62
|
+
:action => component_name,
|
63
|
+
:method => action,
|
64
|
+
:result => result.present? && result.l || {}
|
65
|
+
}.to_json
|
66
|
+
end
|
88
67
|
|
89
|
-
|
90
|
-
|
68
|
+
# The dispatcher for the old-style requests (used for multi-part form submission). The URL contains the name of the component,
|
69
|
+
# as well as the method of this component to be called, according to the double underscore notation.
|
70
|
+
# E.g.: some_grid__post_grid_data.
|
71
|
+
def endpoint_dispatch(endpoint_path)
|
72
|
+
component_name, *sub_components = endpoint_path.split('__')
|
73
|
+
component_instance = Netzke::Base.instance_by_config(session[:netzke_components][component_name.to_sym])
|
74
|
+
|
75
|
+
# We can't do this here; this method is only used for classic form submission, and the response from the server should be the (default) "text/html"
|
76
|
+
# response.headers["Content-Type"] = "text/plain; charset=utf-8"
|
77
|
+
|
78
|
+
render :text => component_instance.invoke_endpoint(sub_components.join("__"), params).to_nifty_json, :layout => false
|
79
|
+
end
|
91
80
|
|
92
81
|
end
|