netzke-core 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/.autotest +1 -1
  2. data/.gitignore +4 -2
  3. data/CHANGELOG.rdoc +37 -15
  4. data/README.rdoc +93 -28
  5. data/Rakefile +5 -7
  6. data/TODO +24 -3
  7. data/app/controllers/netzke_controller.rb +70 -0
  8. data/app/models/netzke_preference.rb +170 -0
  9. data/autotest/discover.rb +2 -3
  10. data/features/actions.feature +13 -0
  11. data/features/basic.feature +7 -0
  12. data/features/client-server.feature +15 -0
  13. data/features/complex_component.feature +18 -0
  14. data/features/component.feature +13 -0
  15. data/features/component_loader.feature +31 -0
  16. data/features/composition.feature +32 -0
  17. data/features/custom_css.feature +17 -0
  18. data/features/file_inclusion.feature +13 -0
  19. data/features/inheritance.feature +19 -0
  20. data/features/persistence.feature +16 -0
  21. data/features/scopes.feature +17 -0
  22. data/features/step_definitions/custom_css_steps.rb +7 -0
  23. data/features/step_definitions/generic_steps.rb +15 -0
  24. data/features/step_definitions/web_steps.rb +219 -0
  25. data/features/support/env.rb +62 -0
  26. data/features/support/paths.rb +45 -0
  27. data/generators/netzke_core/USAGE +3 -3
  28. data/generators/netzke_core/netzke_core_generator.rb +8 -0
  29. data/install.rb +1 -1
  30. data/javascripts/core.js +542 -499
  31. data/lib/generators/migration_helper.rb +32 -0
  32. data/lib/generators/netzke/USAGE +9 -0
  33. data/lib/generators/netzke/core_generator.rb +24 -0
  34. data/lib/netzke/actions.rb +102 -0
  35. data/lib/netzke/base.rb +77 -529
  36. data/lib/netzke/composition.rb +251 -0
  37. data/lib/netzke/configuration.rb +134 -0
  38. data/lib/netzke/core/masquerading.rb +34 -0
  39. data/lib/netzke/core/session.rb +30 -0
  40. data/lib/netzke/core/version.rb +11 -0
  41. data/lib/netzke/core.rb +53 -0
  42. data/lib/netzke/core_ext/array.rb +30 -0
  43. data/lib/netzke/core_ext/hash.rb +84 -0
  44. data/lib/netzke/core_ext/string.rb +26 -0
  45. data/lib/netzke/core_ext/symbol.rb +13 -0
  46. data/lib/netzke/core_ext/time_with_zone.rb +7 -0
  47. data/lib/netzke/core_ext.rb +5 -141
  48. data/lib/netzke/embedding.rb +21 -0
  49. data/lib/netzke/ext_component.rb +25 -0
  50. data/lib/netzke/javascript.rb +248 -0
  51. data/lib/netzke/persistence.rb +118 -0
  52. data/lib/netzke/rails/action_view_ext.rb +103 -0
  53. data/lib/netzke/{controller_extensions.rb → rails/controller_extensions.rb} +7 -2
  54. data/lib/netzke/rails/routes.rb +7 -0
  55. data/lib/netzke/services.rb +68 -0
  56. data/lib/netzke/session.rb +35 -0
  57. data/lib/netzke/stylesheets.rb +52 -0
  58. data/lib/netzke-core.rb +28 -29
  59. data/netzke-core.gemspec +253 -0
  60. data/spec/component/actions_spec.rb +94 -0
  61. data/spec/component/base_spec.rb +25 -0
  62. data/spec/component/composition_spec.rb +132 -0
  63. data/spec/component/javascript_spec.rb +15 -0
  64. data/spec/core_ext_spec.rb +16 -0
  65. data/spec/spec.opt +2 -0
  66. data/spec/spec_helper.rb +35 -0
  67. data/{test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb → templates/core/create_netzke_preferences.rb} +4 -4
  68. data/test/rails_app/.gitignore +4 -0
  69. data/test/rails_app/Gemfile +36 -0
  70. data/test/rails_app/Gemfile.lock +137 -0
  71. data/test/rails_app/README +15 -0
  72. data/test/rails_app/Rakefile +7 -0
  73. data/test/rails_app/app/components/border_layout_panel.rb +4 -0
  74. data/test/rails_app/app/components/component_loader.rb +59 -0
  75. data/test/rails_app/app/components/component_with_actions.rb +58 -0
  76. data/test/rails_app/app/components/component_with_custom_css.rb +8 -0
  77. data/test/rails_app/app/components/component_with_included_js.rb +16 -0
  78. data/test/rails_app/app/components/component_with_session_persistence.rb +25 -0
  79. data/test/rails_app/app/components/custom.css +3 -0
  80. data/test/rails_app/app/components/deprecated/server_caller.rb +20 -0
  81. data/test/rails_app/app/components/extended_component_with_actions.rb +5 -0
  82. data/test/rails_app/app/components/extended_server_caller.rb +18 -0
  83. data/test/rails_app/app/components/included.js +5 -0
  84. data/test/rails_app/app/components/kinda_complex_component/basic_stuff.rb +35 -0
  85. data/test/rails_app/app/components/kinda_complex_component/extra_stuff.rb +16 -0
  86. data/test/rails_app/app/components/kinda_complex_component.rb +7 -0
  87. data/test/rails_app/app/components/loader_of_component_with_custom_css.rb +15 -0
  88. data/test/rails_app/app/components/scoped_components/deep_scoped_components/some_deep_scoped_component.rb +7 -0
  89. data/test/rails_app/app/components/scoped_components/extended_scoped_component.rb +5 -0
  90. data/test/rails_app/app/components/scoped_components/some_scoped_component.rb +5 -0
  91. data/test/rails_app/app/components/server_caller.rb +21 -0
  92. data/test/rails_app/app/components/simple_component.rb +5 -0
  93. data/test/rails_app/app/components/simple_tab_panel.rb +27 -0
  94. data/test/rails_app/app/components/simple_window.rb +3 -0
  95. data/test/rails_app/app/components/some_composite.rb +65 -0
  96. data/test/rails_app/app/components/some_ext_component.rb +8 -0
  97. data/test/{app_root → rails_app}/app/controllers/application_controller.rb +1 -0
  98. data/test/rails_app/app/controllers/components_controller.rb +12 -0
  99. data/test/rails_app/app/controllers/multiple_components_controller.rb +2 -0
  100. data/test/rails_app/app/controllers/welcome_controller.rb +5 -0
  101. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  102. data/test/rails_app/app/views/layouts/application.html.erb +13 -0
  103. data/test/rails_app/app/views/multiple_components/set_one.html.erb +3 -0
  104. data/test/rails_app/config/application.rb +45 -0
  105. data/test/rails_app/config/boot.rb +13 -0
  106. data/test/rails_app/config/database.yml +22 -0
  107. data/test/rails_app/config/environment.rb +6 -0
  108. data/test/rails_app/config/environments/development.rb +22 -0
  109. data/test/rails_app/config/environments/production.rb +49 -0
  110. data/test/rails_app/config/environments/test.rb +35 -0
  111. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  112. data/test/rails_app/config/initializers/inflections.rb +10 -0
  113. data/test/rails_app/config/initializers/mime_types.rb +5 -0
  114. data/test/rails_app/config/initializers/netzke.rb +3 -0
  115. data/test/rails_app/config/initializers/secret_token.rb +7 -0
  116. data/test/rails_app/config/initializers/session_store.rb +8 -0
  117. data/test/rails_app/config/locales/en.yml +5 -0
  118. data/test/rails_app/config/routes.rb +64 -0
  119. data/test/rails_app/config.ru +4 -0
  120. data/test/rails_app/db/development_structure.sql +4 -0
  121. data/{generators/netzke_core/templates/create_netzke_preferences.rb → test/rails_app/db/migrate/20100905214933_create_netzke_preferences.rb} +1 -3
  122. data/test/rails_app/db/schema.rb +24 -0
  123. data/test/rails_app/db/seeds.rb +7 -0
  124. data/test/{app_root/config/environments/in_memory.rb → rails_app/lib/tasks/.gitkeep} +0 -0
  125. data/test/rails_app/public/404.html +26 -0
  126. data/test/rails_app/public/422.html +26 -0
  127. data/test/rails_app/public/500.html +26 -0
  128. data/test/{app_root/config/environments/mysql.rb → rails_app/public/favicon.ico} +0 -0
  129. data/test/rails_app/public/images/rails.png +0 -0
  130. data/test/rails_app/public/robots.txt +5 -0
  131. data/test/rails_app/script/rails +6 -0
  132. data/test/{app_root/config/environments/postgresql.rb → rails_app/vendor/plugins/.gitkeep} +0 -0
  133. data/test/unit/netzke_core_test.rb +74 -75
  134. data/test/unit/netzke_preference_test.rb +2 -2
  135. metadata +176 -48
  136. data/lib/app/controllers/netzke_controller.rb +0 -46
  137. data/lib/app/models/netzke_preference.rb +0 -171
  138. data/lib/netzke/action_view_ext.rb +0 -81
  139. data/lib/netzke/base_js.rb +0 -339
  140. data/lib/netzke/routing.rb +0 -9
  141. data/test/app_root/app/models/role.rb +0 -3
  142. data/test/app_root/app/models/user.rb +0 -3
  143. data/test/app_root/config/boot.rb +0 -115
  144. data/test/app_root/config/database.yml +0 -31
  145. data/test/app_root/config/environment.rb +0 -14
  146. data/test/app_root/config/environments/sqlite.rb +0 -0
  147. data/test/app_root/config/environments/sqlite3.rb +0 -0
  148. data/test/app_root/config/routes.rb +0 -4
  149. data/test/app_root/db/migrate/20090423214303_create_roles.rb +0 -11
  150. data/test/app_root/db/migrate/20090423222114_create_users.rb +0 -12
  151. data/test/app_root/lib/console_with_fixtures.rb +0 -4
  152. data/test/app_root/script/console +0 -7
data/.autotest CHANGED
@@ -1 +1 @@
1
- require 'autotest/redgreen'
1
+ # require 'autotest/redgreen'
data/.gitignore CHANGED
@@ -4,5 +4,7 @@ doc
4
4
  Manifest
5
5
  .DS_Store
6
6
  rdoc
7
- netzke-core.gemspec
8
- *.tmproj
7
+ test/rails_app/tmp/
8
+ test/rails_app/public/extjs
9
+ test/rails_app/public/images/icons
10
+ *.gem
data/CHANGELOG.rdoc CHANGED
@@ -1,10 +1,32 @@
1
- = v0.5.5 - 2010-09-08
2
- * Merge with pschyska/netzke-core - relative_root_url, jsmin
3
- * Detecting actions in config now works on any level
4
-
5
- = v0.5.4 - 2010-08-11
6
- * New: added Netzke.pre name space for pre-built static JS code
7
-
1
+ = v0.6.0 - 2010-10-24
2
+ * Rails3 compatibility, thorough rewrite
3
+ * Much more thorough testing
4
+
5
+ * API backward incompatibility
6
+ * +ext_config+ config level is removed; put all that configuration in the top level
7
+ * mentioning actions in the +bbar+, +tbar+, etc, should be explicit, e.g.:
8
+
9
+ :bbar => [:apply.action, :delete.action]
10
+
11
+ * +late_aggregatee+ is now +lazy_loading+
12
+ * +aggregatees+ are now +components+
13
+ * +widgets+ are now +components+, too
14
+ * +api+ is now +endpoint+
15
+ * +persistent_config_enabled?+ is now +persistence_enabled?+
16
+ * Using the +js_extend_properties+ class method in your components in deprecated (and maybe even broken). Use +js_property+ (or +js_properties+) and +js_method+ instead (see multiple examples in test/rails_app)
17
+ * the +load_component_with_cache+ endpoint renamed to +deliver_component+
18
+
19
+ * New
20
+ * +ext+ helper in the views to embed any (pure) Ext component into a view
21
+ * +component+ DSL method to declare child components
22
+ * +config+ DSL method to set the configuration of an instance
23
+ * +action+ DSL method to configure actions
24
+ * +js_method+ DSL method to define (public) methods in JS class
25
+ * +js_property+ DSL method to define (public) properties in JS class
26
+ * +endpoint+ DSL method to define server endpoints
27
+
28
+ * Different deprecations throughout the code
29
+
8
30
  = v0.5.3 - 2010-06-14
9
31
  * Fix: Getting rid of deprecation warnings about tasks not sitting in lib.
10
32
 
@@ -47,7 +69,7 @@
47
69
  * Code: lightly better test coverage
48
70
  * New: <tt>Netzke::Base#global_id_by_reference</tt> method
49
71
  * Compatibility: resolving conflicts with the <tt>api</tt> property in some Ext v3.0 components
50
- * Fix: <tt>load_aggregatee_with_cache</tt> was throwing exception when the requested aggregatee wasn't defined
72
+ * Fix: <tt>deliver_component</tt> was throwing exception when the requested component wasn't defined
51
73
  * New: <tt>persistent_config_id</tt> configuration option allows specifying an id by which persistent configuration is identified for the widget. Handy if different homogeneous widgets need to share the same persistent configuration.
52
74
  * New: <tt>Netzke::Base#persistent_config</tt> method now accepts an optional boolean parameter signalizing that the configuration is global (not bound to a widget)
53
75
  * Impr: cleaner handling of actions and toolbars; fbar configuration introduced.
@@ -60,10 +82,10 @@
60
82
  * Internal: the JavaScript instance now knows if persistent config is enabled (by checking this.persistentConfig).
61
83
  * Fix: solving the "Node cannot be inserted at the specified point in the hierarchy" problem by being more strict with duplicated IDs for elements on the same page.
62
84
  * Fix: Ext 3.0 compatibility.
63
- * Impr: <tt>getChildWidget</tt> now allows referring to a widget like this: "parent__parent__some_widget__some_nested_widget"
85
+ * Impr: <tt>getChildComponent</tt> now allows referring to a widget like this: "parent__parent__some_widget__some_nested_widget"
64
86
 
65
87
  = v0.4.3
66
- * Fix: reworking loadAggregatee()-related code, closing a security flaw when a malicious browser could send any configuration options to instantiate the widget being loaded.
88
+ * Fix: reworking loadComponent()-related code, closing a security flaw when a malicious browser could send any configuration options to instantiate the widget being loaded.
67
89
 
68
90
  = v0.4.2 - 2009-09-11
69
91
  * Fix: the API call (at the JavaScript side) was ignoring the callback parameter.
@@ -95,7 +117,7 @@
95
117
  * New: widgets now can check session[:netzke_just_logged_in] and session[:netzke_just_logged_out] automatically set by Netzke after login/logout
96
118
 
97
119
  = v0.2.11
98
- * Introduction of getOwnerWidget()-method to Ext.Component. It provides the Netzke widget this Component belongs to.
120
+ * Introduction of getOwnerComponent()-method to Ext.Component. It provides the Netzke widget this Component belongs to.
99
121
 
100
122
  = v0.2.10
101
123
  * Removed dependency on 'json' gem.
@@ -117,11 +139,11 @@
117
139
  = v0.2.6
118
140
  * FeedackGhost is now capable of displaying multiple flash messages.
119
141
  * Dependencies slightly refactored.
120
- * An informative exception added to Base#aggregatee_instance.
142
+ * An informative exception added to Base#component_instance.
121
143
  * JS-level inheritance enabled.
122
- * Work-around for the problem with Ext 2.2.1 in loadWidget.
144
+ * Work-around for the problem with Ext 2.2.1 in loadComponent.
123
145
  * Events "<action_id>click" added to the widgets along with the actions.
124
- * aggregatee_missing method added to Netzke::Base - called when a non-existing aggregate of a widget is tried to be invoked
146
+ * component_missing method added to Netzke::Base - called when a non-existing aggregate of a widget is tried to be invoked
125
147
  * Code readability improvements.
126
148
 
127
149
  = v0.2.5
@@ -132,7 +154,7 @@
132
154
 
133
155
  = v0.2.3
134
156
  * FeedbackGhost will show the feedback on the top of the screen independent of the page scrolling.
135
- * Ext.Panel#loadWidget will accept null as url to delete the currently loaded widget
157
+ * Ext.Panel#loadComponent will accept null as url to delete the currently loaded widget
136
158
  * Bug fix: persistent_config works again
137
159
 
138
160
  = v0.2.2
data/README.rdoc CHANGED
@@ -1,60 +1,125 @@
1
1
  = netzke-core
2
- Create Ext JS + Rails reusable components (widgets) with minimum effort.
3
2
 
4
- This is the bare bones of the Netzke framework. Use it to build your own widgets from scratch. For pre-built widgets (like panels, grids, forms, trees, applications), see the netzke-basepack (http://github.com/skozlov/netzke-basepack) project.
3
+ Create Ext JS + Rails components with minimum effort.
5
4
 
6
- The idea behind the Netzke framework is that it allows you write reusable client/server code. Create a widget, and then embed it (or load it dynamically) into your Ext-based applications or HTML pages. For more info, see the links below.
5
+ This is the bare bones of the Netzke framework. Use it to build your own components from scratch. For pre-built components (like panels, grids, forms, trees, applications), see the netzke-basepack (http://github.com/skozlov/netzke-basepack) project.
7
6
 
8
- == Instalation
9
- For the latest ("edge") stuff, install as plugin (recommended!):
7
+ The idea behind the Netzke framework is that it allows you write reusable client/server code. Create a component, and then embed it straight to your Rails' view, load it dynamically into your Ext-based applications, or use it as a building block for other (composite) components. For more info, see the links below.
10
8
 
11
- ./script/plugin install git://github.com/skozlov/netzke-core.git
9
+ == Requirements
12
10
 
13
- Otherwise, install as gem:
11
+ * Rails >= 3.0.0
12
+ * Ruby >= 1.9.2 (1.8.7 should work, but may not be supported as diligently)
13
+ * Ext >= 3.3.0
14
14
 
15
- gem install netzke-core
16
-
17
- To generate the migrations for Netzke persistent storage (if you want to use it):
15
+ == Installation
16
+
17
+ For the latest ("edge") stuff, tell bundler to get the gem straight from github:
18
18
 
19
- ./script/generate netzke_core
19
+ gem 'netzke-core', :git => "git://github.com/skozlov/netzke-core.git"
20
20
 
21
- Netzke assumes that your ExtJS library is in public/extjs (which may be a symbolic link).
21
+ Or install as plugin:
22
+
23
+ rails plugin install git://github.com/skozlov/netzke-core.git
24
+
25
+ Netzke assumes that your ExtJS library is in public/extjs (which may be a symbolic link):
26
+
27
+ ln -s ~/code/sencha/ext-3.3.0 public/extjs
22
28
 
23
29
  == Usage
24
- Here's how to embed a Netzke widget into your Rails view.
25
30
 
26
- 1. In your layout, within the "head" tag, use the <tt>netzke_init</tt> helper to include all the necessary JavaScript and styles.
31
+ Let's create a simple "Hello world!" component and embed it into a Rails' view. It'll be an Ext.Panel-based component with a button that triggers a client-server communication.
32
+
33
+ Create YOUR_APP/app/components/hello_world_component.rb, and put in the following content:
34
+
35
+ class HelloWorldComponent < Netzke::Base
36
+ # Ext.Panel's config option "title"
37
+ js_property :title, "My Hello World Component"
38
+
39
+ # Bottom bar with an automatically created action
40
+ js_property :bbar, [:bug_server.action]
41
+
42
+ # Method in the JS class that (by default) processes the action's "click" event
43
+ js_method :on_bug_server, <<-JS
44
+ function(){
45
+ // Remotely calling the server's method greet_the_world (defined below)
46
+ this.greetTheWorld();
47
+ }
48
+ JS
49
+
50
+ # Server's method that gets called from the JS
51
+ endpoint :greet_the_world do |params|
52
+ # Tell the client side to call its method showGreeting with "Hello World!" as parameter
53
+ {:show_greeting => "Hello World!"}
54
+ end
55
+
56
+ # Another method in the JS class that gets remotely called by the server side
57
+ js_method :show_greeting, <<-JS
58
+ function(greeting){
59
+ this.body.update("Server says: " + greeting);
60
+ }
61
+ JS
62
+ end
63
+
64
+
65
+ To embed a Netzke component into your Rails view do the following:
66
+
67
+ 1. In your layout, within the "head" tag, use the <tt>netzke_init</tt> helper to include all the necessary JavaScript and styles.
27
68
 
28
69
  <%= netzke_init %>
29
-
30
- 2. In config/routes.rb declare the Netzke routes:
31
70
 
32
- map.netzke
71
+ You can optionally specify an Ext theme:
72
+
73
+ <%= netzke_init :ext_theme => 'grey' %>
74
+
75
+ 2. In your view use the <tt>netzke</tt> helper to embed the component:
76
+
77
+ <%= netzke :hello_world_component %>
78
+
79
+ That's it. While playing with the component, use Firebug or similar tool to check the AJAX requests to understand better what's going on behind the scenes. Also check the source code of the page embedding the component.
80
+
81
+ == Running tests
82
+
83
+ netzke-core is bundled with cucumber and RSpec tests. Before you can run them, you must link your Ext JS library to test/rails_app/public, e.g. (from plugin's root):
84
+
85
+ ln -s ~/code/sencha/ext-3.3.0 test/rails_app/public/extjs
86
+
87
+ For cucumber tests:
88
+
89
+ cucumber features
33
90
 
34
- 3. In your view use the <tt>netzke</tt> helper wherever you want to insert a widget.
91
+ RSpec tests:
35
92
 
36
- <%= netzke :grid_panel, :model => "User", :columns => [:id, :name, :created_at] %>
93
+ rspec spec
37
94
 
38
- (here we use the GridPanel widget from the netzke-basepack project)
95
+ == Testing playground
96
+
97
+ The bundled test/rails_app application is also a convenient playground to learn more about the framework, as it may be run as a stand-alone Rails app. It's also a pretty good source of examples. After starting it, access any of the app/components/netzke test components by using the following url:
98
+
99
+ http://localhost:3000/components/<name of the component's class>
39
100
 
40
- == Running in production
101
+ e.g.:
102
+
103
+ http://localhost:3000/components/ServerCaller
41
104
 
42
- 1. There is some basic JS minification when running in production. This uses JSMin to strip comments, whitespace etc.
105
+ or, for scoped components:
43
106
 
44
- It can also manually configured by setting :minify_js
107
+ http://localhost:3000/components/ScopedComponents::SomeScopedComponent
45
108
 
46
- Netzke::Base.configure :minify_js=>true
109
+ == Migrating from 0.5.x
110
+
111
+ There have been a significant amount of changes that made 0.6 version backward-incompatible. Please, refer to CHANGELOG.rdoc for the (hopefully) full list of changes that most certainly would make your current application break. Additionally, this wiki page may be of some help, too: http://github.com/skozlov/netzke-core/wiki/Upgrading-from-0.5.x-to-0.6.0
47
112
 
48
113
  == More info
49
- Introduction to Netzke framework and wiki: http://github.com/skozlov/netzke
114
+ Netzke website: http://netzke.org
50
115
 
51
- Twitter: http://twitter.com/skozlov
116
+ Live-demo with sample code: http://demo.netzke.org
52
117
 
53
118
  Tutorials: http://blog.writelesscode.com
54
119
 
55
- Live-demo with sample code: http://netzke-demo.writelesscode.com
120
+ Twitter: http://twitter.com/skozlov
56
121
 
57
- The netzke-basepack project (pre-built full-featured widgets): http://github.com/skozlov/netzke-basepack
122
+ The netzke-basepack project (pre-built full-featured components): http://github.com/skozlov/netzke-basepack
58
123
 
59
124
  ---
60
125
 
data/Rakefile CHANGED
@@ -1,31 +1,29 @@
1
1
  begin
2
2
  require 'jeweler'
3
+ require './lib/netzke/core/version'
3
4
  Jeweler::Tasks.new do |gemspec|
4
- gemspec.version = "0.5.5"
5
+ gemspec.version = Netzke::Core::Version::STRING
5
6
  gemspec.name = "netzke-core"
6
- gemspec.summary = "Build ExtJS/Rails widgets with minimum effort"
7
+ gemspec.summary = "Build ExtJS/Rails components with minimum effort"
7
8
  gemspec.description = "Allows building ExtJS/Rails reusable code in a DRY way"
8
9
  gemspec.email = "sergei@playcode.nl"
9
10
  gemspec.homepage = "http://github.com/skozlov/netzke-core"
10
11
  gemspec.rubyforge_project = "netzke-core"
11
12
  gemspec.authors = ["Sergei Kozlov"]
12
- gemspec.add_dependency("jsmin", ">=1.0.1")
13
+ gemspec.add_dependency("activesupport", ">=3.0.1")
13
14
  gemspec.post_install_message = <<-MESSAGE
14
15
 
15
16
  ========================================================================
16
17
 
17
18
  Thanks for installing Netzke Core!
18
19
 
19
- Don't forget to run "./script/generate netzke_core" for each Rails
20
- app that will be using this gem.
21
-
22
20
  Netzke home page: http://netzke.org
23
21
  Netzke Google Groups: http://groups.google.com/group/netzke
24
22
  Netzke tutorials: http://blog.writelesscode.com
25
23
 
26
24
  ========================================================================
27
25
 
28
- MESSAGE
26
+ MESSAGE
29
27
 
30
28
  end
31
29
  Jeweler::GemcutterTasks.new
data/TODO CHANGED
@@ -1,3 +1,24 @@
1
- * Re-factor JS-level inheritance mechanisms (2009-07-5 why?)
2
- * Get rid of the default_config method, because the same functionality maybe achieved by overwriting the initialize method
3
- * late aggregatees should probably be named lazy aggregatees
1
+ Make plugin-wide javascripts and stylesheets load automatically.
2
+ Caching - investigate reusing (fragment?) caching of Rails.
3
+ Use Ext.Direct in the Netzke controller.
4
+ Let specify per API point if it will use a GET or a POST request.
5
+ Re-work generators
6
+
7
+ Some day
8
+ * make gzipping generated JS code possible
9
+
10
+
11
+ = Ideas that didn't work out
12
+
13
+ == Making value from super-class accessible in the block parameters in endpoints, e.g.:
14
+
15
+ endpoint :call_server do |params, orig|
16
+ orig.merge(:set_title => orig[:set_title] + " extended")
17
+ end
18
+
19
+ Bad idea because calling the super method is often required AFTER doing something in the override, not BEFORE. For example, deliver_component in GridPanel in Basepack is overridden to reconfigure the components on the fly before actually delivering the component (i.e. calling super).
20
+ So, to override an endpoint, simply define a method with endpoint's name, e.g.:
21
+
22
+ def call_server(params)
23
+ super.merge(...)
24
+ end
@@ -0,0 +1,70 @@
1
+ class NetzkeController < ApplicationController
2
+
3
+ # Collect javascripts and stylesheets from all plugins that registered it in Netzke::Core.javascripts
4
+ # TODO: caching
5
+ # caches_action :netzke
6
+ def netzke
7
+ respond_to do |format|
8
+ format.js {
9
+ res = initial_dynamic_javascript << "\n"
10
+ Netzke::Core.javascripts.each do |path|
11
+ f = File.new(path)
12
+ res << f.read
13
+ end
14
+
15
+ # If JS classes are not inserted into the main page, we need to render all the classes needed to load the page that includes us
16
+ # (i.e. netzke/netzke.js) here
17
+ if !Netzke::Core.javascript_on_main_page
18
+ rendered_classes = []
19
+ Netzke::Core.session[:netzke_components].each_pair do |k,v|
20
+ component = Netzke::Base.instance_by_config(v)
21
+ res << component.js_missing_code(rendered_classes.map(&:name))
22
+ rendered_classes += component.dependency_classes
23
+ rendered_classes.uniq!
24
+ end
25
+ end
26
+
27
+ render :text => defined?(::Rails) && ::Rails.env.production? ? res.strip_js_comments : res
28
+ }
29
+
30
+ format.css {
31
+ res = ""
32
+ Netzke::Core.stylesheets.each do |path|
33
+ f = File.new(path)
34
+ res << f.read
35
+ end
36
+ render :text => res
37
+ }
38
+ end
39
+ end
40
+
41
+ # Main dispatcher of the HTTP requests. The URL contains the name of the component,
42
+ # as well as the method of this component to be called, according to the double underscore notation.
43
+ # E.g.: some_grid__post_grid_data.
44
+ def method_missing(method_name)
45
+ component_name, *action = method_name.to_s.split('__')
46
+ component_name = component_name.to_sym
47
+ action = !action.empty? && action.join("__").to_sym
48
+
49
+ if action
50
+ w_instance = Netzke::Base.instance_by_config(Netzke::Core.session[:netzke_components][component_name])
51
+ # only component's actions starting with "endpoint_" are accessible from outside (security)
52
+ endpoint_action = action.to_s.index('__') ? action : "endpoint_#{action}"
53
+ render :text => w_instance.send(endpoint_action, params), :layout => false
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ private
60
+ # Generates initial javascript code that is dependent on Rails environement
61
+ def initial_dynamic_javascript
62
+ res = []
63
+ res << %(Ext.Ajax.extraParams = {authenticity_token: '#{form_authenticity_token}'}; // Rails' forgery protection)
64
+ res << %{Ext.ns('Netzke');}
65
+ res << %{Netzke.RelativeUrlRoot = '#{ActionController::Base.config.relative_url_root}';}
66
+ res << %{Netzke.RelativeExtUrl = '#{ActionController::Base.config.relative_url_root}/extjs';}
67
+ res.join("\n")
68
+ end
69
+
70
+ end
@@ -0,0 +1,170 @@
1
+ class NetzkePreference < ActiveRecord::Base
2
+ serialize :value
3
+
4
+ # belongs_to :user
5
+ # belongs_to :role
6
+
7
+ # ELEMENTARY_CONVERTION_METHODS= {'Fixnum' => 'to_i', 'String' => 'to_s', 'Float' => 'to_f', 'Symbol' => 'to_sym'}
8
+
9
+ # def self.component_name=(value)
10
+ # @@component_name = value
11
+ # end
12
+ #
13
+ # def self.component_name
14
+ # @@component_name ||= nil
15
+ # end
16
+
17
+ # def normalized_value
18
+ # klass = read_attribute(:pref_type)
19
+ # norm_value = read_attribute(:value)
20
+ #
21
+ # case klass
22
+ # when nil then r = norm_value # do not cast
23
+ # when 'Boolean' then r = norm_value == 'false' ? false : (norm_value == 'true' || norm_value)
24
+ # when 'NilClass' then r = nil
25
+ # when 'Array', 'Hash' then r = ActiveSupport::JSON.decode(norm_value)
26
+ # else
27
+ # r = norm_value.send(ELEMENTARY_CONVERTION_METHODS[klass])
28
+ # end
29
+ # r
30
+ # end
31
+ #
32
+ # def normalized_value=(new_value)
33
+ # case new_value.class.name
34
+ # when "Array" then write_attribute(:value, new_value.to_json)
35
+ # when "Hash" then write_attribute(:value, new_value.to_json)
36
+ # else write_attribute(:value, new_value.to_s)
37
+ # end
38
+ # write_attribute(:pref_type, [TrueClass, FalseClass].include?(new_value.class) ? 'Boolean' : new_value.class.to_s)
39
+ # end
40
+ #
41
+ # def self.[](pref_name)
42
+ # pref_name = normalize_preference_name(pref_name)
43
+ # pref = self.pref_to_read(pref_name)
44
+ # pref && pref.normalized_value
45
+ # end
46
+ #
47
+ # def self.[]=(pref_name, new_value)
48
+ # pref_name = normalize_preference_name(pref_name)
49
+ # pref = self.pref_to_write(pref_name)
50
+ #
51
+ # # if assigning nil, simply delete the eventually found preference
52
+ # if new_value.nil?
53
+ # pref && pref.destroy
54
+ # else
55
+ # # pref ||= self.new(conditions(pref_name))
56
+ # pref.normalized_value = new_value
57
+ # pref.save!
58
+ # end
59
+ # end
60
+
61
+
62
+
63
+ # Overwrite pref_to_read, pref_to_write methods, and find_all_for_component if you want a different way of
64
+ # identifying the proper preference based on your own authorization strategy.
65
+ #
66
+ # The default strategy is:
67
+ # 1) if no masq_user or masq_role defined
68
+ # pref_to_read will search for the preference for user first, then for user's role
69
+ # pref_to_write will always find or create a preference for the current user (never for its role)
70
+ # 2) if masq_user or masq_role is defined
71
+ # pref_to_read and pref_to_write will always take the masquerade into account, e.g. reads/writes will go to
72
+ # the user/role specified
73
+ #
74
+ def self.pref_to_read(name)
75
+ name = name.to_s
76
+ session = Netzke::Core.session
77
+ cond = {:key => name}
78
+
79
+ if session[:masq_user]
80
+ # first, get the prefs for this user it they exist
81
+ res = self.where(cond.merge({:user_id => session[:masq_user]})).first
82
+
83
+ # if it doesn't exist, get them for the user's role
84
+ user = User.where(session[:masq_user])
85
+ res ||= self.where(cond.merge({:role_id => user.role.id})).first
86
+
87
+ # if it doesn't exist either, get them for the World (role_id = 0)
88
+ res ||= self.where(cond.merge({:role_id => 0})).first
89
+ elsif session[:masq_role]
90
+ # first, get the prefs for this role
91
+ res = self.where(cond.merge({:role_id => session[:masq_role]})).first
92
+ # if it doesn't exist, get them for the World (role_id = 0)
93
+ res ||= self.where(cond.merge({:role_id => 0})).first
94
+ elsif session[:netzke_user_id]
95
+ user = User.where(session[:netzke_user_id])
96
+ # first, get the prefs for this user
97
+ res = self.where(cond.merge({:user_id => user.id})).first
98
+ # if it doesn't exist, get them for the user's role
99
+ res ||= self.where(cond.merge({:role_id => user.role.id})).first
100
+ # if it doesn't exist either, get them for the World (role_id = 0)
101
+ res ||= self.where(cond.merge({:role_id => 0})).first
102
+ else
103
+ res = self.where(cond).first
104
+ end
105
+
106
+ res
107
+ end
108
+
109
+ def self.pref_to_write(name)
110
+ name = name.to_s
111
+ session = Netzke::Core.session
112
+ cond = {:key => name}
113
+
114
+ if session[:masq_user]
115
+ cond.merge!({:user_id => session[:masq_user]})
116
+ # first, try to find the preference for masq_user
117
+ res = self.where(cond).first
118
+ # if it doesn't exist, create it
119
+ res ||= self.new(cond)
120
+ elsif session[:masq_role]
121
+ # first, delete all the corresponding preferences for the users that have this role
122
+ Role.where(session[:masq_role]).users.each do |u|
123
+ self.delete_all(cond.merge({:user_id => u.id}))
124
+ end
125
+ cond.merge!({:role_id => session[:masq_role]})
126
+ res = self.where(cond).first
127
+ res ||= self.new(cond)
128
+ elsif session[:masq_world]
129
+ # first, delete all the corresponding preferences for all users and roles
130
+ self.delete_all(cond)
131
+ # then, create the new preference for the World (role_id = 0)
132
+ res = self.new(cond.merge(:role_id => 0))
133
+ elsif session[:netzke_user_id]
134
+ res = self.where(cond.merge({:user_id => session[:netzke_user_id]})).first
135
+ res ||= self.new(cond.merge({:user_id => session[:netzke_user_id]}))
136
+ else
137
+ res = self.where(cond).first
138
+ res ||= self.new(cond)
139
+ end
140
+ res
141
+ end
142
+
143
+ # def self.find_all_for_component(name)
144
+ # session = Netzke::Core.session
145
+ # cond = {:component_name => name}
146
+ #
147
+ # if session[:masq_user] || session[:masq_role]
148
+ # cond.merge!({:user_id => session[:masq_user], :role_id => session[:masq_role]})
149
+ # res = self.where(cond).all
150
+ # elsif session[:netzke_user_id]
151
+ # user = User.where(session[:netzke_user_id])
152
+ # res = self.where(cond.merge({:user_id => session[:netzke_user_id]})).all
153
+ # res += self.where(cond.merge({:role_id => user.role.try(:id)})).all
154
+ # else
155
+ # res = self.where(cond).all
156
+ # end
157
+ #
158
+ # res
159
+ # end
160
+
161
+ # def self.delete_all_for_component(name)
162
+ # self.destroy(find_all_for_component(name))
163
+ # end
164
+ #
165
+ # private
166
+ # def self.normalize_preference_name(name)
167
+ # name.to_s.gsub(".", "__").gsub("/", "__")
168
+ # end
169
+
170
+ end
data/autotest/discover.rb CHANGED
@@ -1,3 +1,2 @@
1
- Autotest.add_discovery do
2
- "rails"
3
- end
1
+ Autotest.add_discovery { "rails" }
2
+ Autotest.add_discovery { "rspec2" }
@@ -0,0 +1,13 @@
1
+ Feature: Actions
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @javascript
7
+ Scenario: Pressing button should result in corresponding actions
8
+ When I go to the ComponentWithActions test page
9
+ Then I should see "Disabled action"
10
+ And button "Disabled action" should be disabled
11
+
12
+ When I press "Some action"
13
+ Then I should see "Some action was triggered"
@@ -0,0 +1,7 @@
1
+ Feature: Basic Netzke functionality
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ Scenario: Initial loading
7
+ Then Netzke should be initialized
@@ -0,0 +1,15 @@
1
+ Feature: Client/server communication
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @selenium
7
+ Scenario: Ask server to set our title
8
+ Given I am on the ServerCaller test page
9
+ Then I should see "Server Caller"
10
+
11
+ # When I execute "Ext.getCmp('server_caller').buttons.first().fireEvent('click');"
12
+ When I press "Call server"
13
+ Then I should see "All quiet here on the server"
14
+
15
+
@@ -0,0 +1,18 @@
1
+ Feature: Complex component
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @javascript
7
+ Scenario: Complex component must render properly
8
+ When I go to the KindaComplexComponent test page
9
+ Then I should see "Panel One"
10
+ And I should see "Panel Two"
11
+ And I should see "Server Caller"
12
+
13
+ @javascript
14
+ Scenario: The last tab of the complex component is a Netzke component that just works
15
+ Given I am on the KindaComplexComponent test page
16
+ When I follow "Server Caller"
17
+ And I press "Call server"
18
+ Then I should see "All quiet here on the server"
@@ -0,0 +1,13 @@
1
+ Feature: Testing Netzke::Base
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @javascript
7
+ Scenario: A panel should render nicely
8
+ When I go to the SimpleComponent test page
9
+ Then I should see "SimpleComponent"
10
+ And I should see "Inner text"
11
+
12
+
13
+