netzke-core 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,12 @@
1
+ = v0.5.2 - EDGE
2
+ * Ext 3.2.1
3
+ * Fix: Netzke::Base.before_load is now also called for the widgets embedded directly into a view.
4
+ * New: support for external stylesheets.
5
+ * Fix: the "value" column type has been changed to text to prevent migration problems is some cases
6
+ * New: global_persistent_config method allows accessing persistent storage with no owner (widget) assigned
7
+ * New: any widget can now implement <tt>before_api_call</tt> interceptor. If it returns anything but empty hash, it'll be used as the result of *any* API call to this widget. The interceptor receives as parameter the name of the API call issued and the arguments. Use it to implement authorization.
8
+ * Fix: got the Ext's state provider out of the way (thank you for all the confusion)
9
+
1
10
  = v0.5.1 - 2010-02-26
2
11
  * Compatibility with Ext 3.1.1
3
12
  * New: <tt>Netzke.page</tt> object now contains all the widgets declared on the page
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  begin
2
2
  require 'jeweler'
3
3
  Jeweler::Tasks.new do |gemspec|
4
- gemspec.version = "0.5.1"
4
+ gemspec.version = "0.5.2"
5
5
  gemspec.name = "netzke-core"
6
6
  gemspec.summary = "Build ExtJS/Rails widgets with minimum effort"
7
7
  gemspec.description = "Allows building ExtJS/Rails reusable code in a DRY way"
@@ -9,6 +9,22 @@ begin
9
9
  gemspec.homepage = "http://github.com/skozlov/netzke-core"
10
10
  gemspec.rubyforge_project = "netzke-core"
11
11
  gemspec.authors = ["Sergei Kozlov"]
12
+ gemspec.post_install_message = <<-MESSAGE
13
+
14
+ ========================================================================
15
+
16
+ Thanks for installing Netzke Core!
17
+
18
+ Run "./script/generate netzke_core" to finish the installation.
19
+
20
+ Netzke home page: http://netzke.org
21
+ Netzke Google Groups: http://groups.google.com/group/netzke
22
+ Netzke tutorials: http://blog.writelesscode.com
23
+
24
+ ========================================================================
25
+
26
+ MESSAGE
27
+
12
28
  end
13
29
  Jeweler::GemcutterTasks.new
14
30
  rescue LoadError
@@ -2,12 +2,9 @@
2
2
  class NetzkeCoreGenerator < Rails::Generator::Base
3
3
  def manifest
4
4
  record do |m|
5
- # FIXME: how do we avoid getting the same migration timestamps?
6
- # Work-around
7
- time = Time.now.utc.strftime("%Y%m%d%H%M%S")
8
- m.directory 'db/migrate'
9
- # m.file 'create_netzke_layouts.rb', "db/migrate/#{time}_create_netzke_layouts.rb"
10
- m.file 'create_netzke_preferences.rb', "db/migrate/#{time.to_i+1}_create_netzke_preferences.rb"
5
+ m.migration_template 'create_netzke_preferences.rb', 'db/migrate', :assigns => {
6
+ :migration_name => "CreateNetzkePreferences"
7
+ }, :migration_file_name => "create_netzke_preferences"
11
8
  end
12
9
  end
13
10
  end
@@ -1,12 +1,12 @@
1
1
  class CreateNetzkePreferences < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table :netzke_preferences do |t|
4
- t.string :name
5
- t.string :pref_type
6
- t.string :value, :limit => 65535
4
+ t.string :name
5
+ t.string :pref_type
6
+ t.text :value
7
7
  t.integer :user_id
8
8
  t.integer :role_id
9
- t.string :widget_name
9
+ t.string :widget_name
10
10
 
11
11
  t.timestamps
12
12
  end
data/javascripts/core.js CHANGED
@@ -3,11 +3,13 @@ This file gets loaded along with the rest of Ext library at the initial load
3
3
  */
4
4
 
5
5
  // Check Ext JS version
6
- var requiredExtVersion = "3.1.1";
7
- var currentExtVersion = Ext.version;
8
- if (requiredExtVersion !== currentExtVersion) {
9
- alert("Netzke needs Ext " + requiredExtVersion + ". You have " + currentExtVersion + ".");
10
- }
6
+ (function(){
7
+ var requiredExtVersion = "3.2.1";
8
+ var currentExtVersion = Ext.version;
9
+ if (requiredExtVersion !== currentExtVersion) {
10
+ alert("Netzke needs Ext " + requiredExtVersion + ". You have " + currentExtVersion + ".");
11
+ }
12
+ })();
11
13
 
12
14
  // Initial stuff
13
15
  Ext.BLANK_IMAGE_URL = "/extjs/resources/images/default/s.gif";
@@ -17,6 +19,9 @@ Ext.ns('Netzke.page'); // namespace for all widget instantces on the page
17
19
 
18
20
  Ext.QuickTips.init();
19
21
 
22
+ // We don't want no state managment by default, thank you!
23
+ Ext.state.Provider.prototype.set = function(){};
24
+
20
25
  // Type detection functions
21
26
  Netzke.isObject = function(o) {
22
27
  return (o != null && typeof o == "object" && o.constructor.toString() == Object.toString());
@@ -1,9 +1,8 @@
1
1
  class NetzkeController < ApplicationController
2
- def index
3
- redirect_to :action => :test_widgets
4
- end
5
-
6
- # collect javascripts from all plugins that registered it in Netzke::Base.config[:javascripts]
2
+
3
+ # Collect javascripts from all plugins that registered it in Netzke::Base.config[:javascripts]
4
+ # TODO: caching
5
+ # caches_action :netzke
7
6
  def netzke
8
7
  respond_to do |format|
9
8
  format.js {
@@ -26,6 +25,9 @@ class NetzkeController < ApplicationController
26
25
  end
27
26
  end
28
27
 
28
+ # Main dispatcher of the HTTP requests. The URL contains the name of the widget,
29
+ # as well as the method of this widget to be called, according to the double underscore notation.
30
+ # E.g.: some_grid__post_grid_data.
29
31
  def method_missing(method_name)
30
32
  widget_name, *action = method_name.to_s.split('__')
31
33
  widget_name = widget_name.to_sym
@@ -3,26 +3,31 @@ module Netzke
3
3
  # Include JavaScript
4
4
  def netzke_js_include
5
5
  # ExtJS
6
- res = ENV['RAILS_ENV'] == 'development' ? javascript_include_tag("/extjs/adapter/ext/ext-base.js", "/extjs/ext-all-debug.js") : javascript_include_tag("/extjs/adapter/ext/ext-base.js", "/extjs/ext-all.js")
6
+ res = ENV['RAILS_ENV'] == 'development' ? javascript_include_tag("/extjs/adapter/ext/ext-base", "/extjs/ext-all-debug") : javascript_include_tag("/extjs/adapter/ext/ext-base", "/extjs/ext-all")
7
7
  # Netzke (dynamically generated)
8
- res << javascript_include_tag("/netzke/netzke.js")
8
+ res << javascript_include_tag("/netzke/netzke")
9
9
  end
10
10
 
11
11
  # Include CSS
12
12
  def netzke_css_include(theme_name = :default)
13
13
  # ExtJS base
14
- res = stylesheet_link_tag("/extjs/resources/css/ext-all.css")
14
+ res = stylesheet_link_tag("/extjs/resources/css/ext-all")
15
15
  # ExtJS theming
16
- res << stylesheet_link_tag("/extjs/resources/css/xtheme-#{theme_name}.css") unless theme_name == :default
16
+ res << stylesheet_link_tag("/extjs/resources/css/xtheme-#{theme_name}") unless theme_name == :default
17
17
  # Netzke (dynamically generated)
18
- res << stylesheet_link_tag("/netzke/netzke.css")
18
+ res << stylesheet_link_tag("/netzke/netzke")
19
+
20
+ # External stylesheets (which cannot be loaded dynamically along with the rest of the widget, e.g. due to that
21
+ # relative paths are used in them)
22
+ res << stylesheet_link_tag(Netzke::Base.config[:external_css])
23
+
19
24
  res
20
25
  end
21
26
 
22
27
  # JavaScript for all Netzke classes in this view, and Ext.onReady which renders all Netzke widgets in this view
23
28
  def netzke_js
24
29
  javascript_tag <<-END_OF_JAVASCRIPT
25
- Ext.Ajax.extraParams = {authenticity_token: '#{form_authenticity_token}'}; // Rails' forgery protection... effective?
30
+ Ext.Ajax.extraParams = {authenticity_token: '#{form_authenticity_token}'}; // Rails' forgery protection
26
31
  #{@content_for_netzke_js_classes}
27
32
  Ext.onReady(function(){
28
33
  #{@content_for_netzke_on_ready}
@@ -48,9 +53,9 @@ module Netzke
48
53
  config[:name] = name
49
54
  Netzke::Base.reg_widget(config)
50
55
  w = Netzke::Base.instance_by_config(config)
56
+ w.before_load # inform the widget about initial load
51
57
  content_for :netzke_js_classes, w.js_missing_code(@rendered_classes ||= [])
52
- content_for :netzke_on_ready, w.js_widget_instance
53
- content_for :netzke_on_ready, w.js_widget_render
58
+ content_for :netzke_on_ready, "#{w.js_widget_instance}\n\n#{w.js_widget_render}"
54
59
 
55
60
  # Now mark this widget's class as rendered, so that we only generate it once per view
56
61
  @rendered_classes << class_name unless @rendered_classes.include?(class_name)
data/lib/netzke/base.rb CHANGED
@@ -51,14 +51,16 @@ module Netzke
51
51
  :javascripts => [],
52
52
  :stylesheets => [],
53
53
 
54
+ :external_css => [],
55
+
54
56
  # AR model that provides us with persistent config functionality
55
57
  :persistent_config_manager => "NetzkePreference",
56
58
 
57
59
  # Default location of extjs library
58
60
  :ext_location => defined?(RAILS_ROOT) && "#{RAILS_ROOT}/public/extjs",
59
61
 
60
- # Default location of icons (TODO: has no effect for now)
61
- :icons_location => defined?(RAILS_ROOT) && "#{RAILS_ROOT}/public/images/icons",
62
+ # Default location of icons, relative to the root of the domain
63
+ :icons_uri => "/images/icons/",
62
64
 
63
65
  # Default instance config
64
66
  :default_config => {
@@ -132,7 +134,8 @@ module Netzke
132
134
  api_points.each do |apip|
133
135
  module_eval <<-END, __FILE__, __LINE__
134
136
  def api_#{apip}(*args)
135
- #{apip}(*args).to_nifty_json
137
+ before_api_call_result = defined?(before_api_call) && before_api_call('#{apip}', *args) || {}
138
+ (before_api_call_result.empty? ? #{apip}(*args) : before_api_call_result).to_nifty_json
136
139
  end
137
140
  # FIXME: commented out because otherwise ColumnOperations stop working
138
141
  # def #{apip}(*args)
@@ -163,6 +166,34 @@ module Netzke
163
166
  rescue NameError
164
167
  nil
165
168
  end
169
+
170
+ # Example:
171
+ # masquarade_as(:role, 2)
172
+ # masquarade_as(:user, 4)
173
+ # masquarade_as(:world)
174
+ def self.masquerade_as(authority_level, authority_id = true)
175
+ reset_masquerading
176
+ session.merge!(:"masq_#{authority_level}" => authority_id)
177
+ end
178
+
179
+ def self.reset_masquerading
180
+ session[:masq_world] = session[:masq_role] = session[:masq_user] = nil
181
+ end
182
+
183
+ # Who are we acting as?
184
+ def self.authority_level
185
+ if session[:masq_world]
186
+ :world
187
+ elsif session[:masq_role]
188
+ [:role, session[:masq_role]]
189
+ elsif session[:masq_user]
190
+ [:user, session[:masq_user]]
191
+ elsif session[:netzke_user_id]
192
+ [:self, session[:netzke_user_id]]
193
+ else
194
+ :none # or nil ?
195
+ end
196
+ end
166
197
 
167
198
  # Widget initialization process
168
199
  # * the config hash is available to the widget after the "super" call in the initializer
@@ -207,14 +238,14 @@ module Netzke
207
238
  !persistent_config_manager_class.nil? && initial_config[:persistent_config]
208
239
  end
209
240
 
210
- # Store some setting in the database as if it was a hash, e.g.:
241
+ # Access to own persistent config, e.g.:
211
242
  # persistent_config["window.size"] = 100
212
243
  # persistent_config["window.size"] => 100
213
- # This method is user-aware
214
- def persistent_config(global = false)
215
- if persistent_config_enabled? || global
244
+ # This method is user/role-aware
245
+ def persistent_config
246
+ if persistent_config_enabled?
216
247
  config_class = self.class.persistent_config_manager_class
217
- config_class.widget_name = global ? nil : persistence_key.to_s # pass to the config class our unique name
248
+ config_class.widget_name = persistence_key.to_s # pass to the config class our unique name
218
249
  config_class
219
250
  else
220
251
  # if we can't use presistent config, all the calls to it will always return nil,
@@ -224,6 +255,13 @@ module Netzke
224
255
  end
225
256
  end
226
257
 
258
+ # Access to the global persistent config (e.g. of another widget)
259
+ def global_persistent_config(owner = nil)
260
+ config_class = self.class.persistent_config_manager_class
261
+ config_class.widget_name = owner
262
+ config_class
263
+ end
264
+
227
265
  # A string which will identify NetzkePreference records for this widget.
228
266
  # If <tt>persistence_key</tt> is passed, use it. Otherwise use global widget's id.
229
267
  def persistence_key #:nodoc:
@@ -414,7 +452,7 @@ module Netzke
414
452
  aggregatee_config = aggregator.aggregatees[aggr]
415
453
  raise ArgumentError, "No aggregatee '#{aggr}' defined for widget '#{aggregator.global_id}'" if aggregatee_config.nil?
416
454
  ::ActiveSupport::Deprecation.warn("widget_class_name option is deprecated. Use class_name instead", caller) if aggregatee_config[:widget_class_name]
417
- short_widget_class_name = aggregatee_config[:class_name] || aggregatee_config[:class_name]
455
+ short_widget_class_name = aggregatee_config[:class_name] || aggregatee_config[:widget_class_name]
418
456
  raise ArgumentError, "No class_name specified for aggregatee #{aggr} of #{aggregator.global_id}" if short_widget_class_name.nil?
419
457
  widget_class = "Netzke::#{short_widget_class_name}".constantize
420
458
 
@@ -37,7 +37,7 @@ module Netzke
37
37
  non_late_aggregatees.each_pair do |aggr_name, aggr_config|
38
38
  aggr_instance = aggregatee_instance(aggr_name.to_sym)
39
39
  aggr_instance.before_load
40
- res["#{aggr_name}_config".to_sym] = aggr_instance.js_config
40
+ res[:"#{aggr_name}_config"] = aggr_instance.js_config
41
41
  end
42
42
 
43
43
  # Api (besides the default "load_aggregatee_with_cache" - JavaScript side already knows about it)
@@ -88,12 +88,12 @@ module Netzke
88
88
 
89
89
  # rendering
90
90
  def js_widget_render
91
- %Q{Netzke.page.#{name.jsonify}.render("#{name.to_s.split('_').join('-')}-div");} unless self.class.js_xtype == "netzkewindow"
91
+ %Q{Netzke.page.#{name.jsonify}.render("#{name.to_s.split('_').join('-')}-netzke");} unless self.class.js_xtype == "netzkewindow"
92
92
  end
93
93
 
94
94
  # container for rendering
95
95
  def js_widget_html
96
- %Q{<div id="#{name.to_s.split('_').join('-')}-div"></div>}
96
+ %Q{<div id="#{name.to_s.split('_').join('-')}-netzke" class="netzke-widget"></div>}
97
97
  end
98
98
 
99
99
  #
@@ -26,6 +26,6 @@ mysql:
26
26
  host: localhost
27
27
  username: root
28
28
  password:
29
- database: plugin_test
29
+ database: netzke_core_test
30
30
  pool: 5
31
31
  timeout: 5000
@@ -29,14 +29,14 @@ class CoreExtTest < ActiveSupport::TestCase
29
29
 
30
30
  test "javascript-like access to hash data" do
31
31
  a = {}
32
- a["key"] = 100
33
- assert_equal(100, a.key)
32
+ a["b"] = 100
33
+ assert_equal(100, a.b)
34
34
 
35
- a.key = 200
36
- assert_equal(200, a["key"])
35
+ a.b = 200
36
+ assert_equal(200, a["b"])
37
37
 
38
- a.another_key = 300
39
- assert_equal(300, a[:another_key])
38
+ a.c = 300
39
+ assert_equal(300, a[:c])
40
40
  end
41
41
 
42
42
  test "jsonify" do
@@ -143,8 +143,8 @@ class NetzkeCoreTest < ActiveSupport::TestCase
143
143
 
144
144
  test "widget instance by config" do
145
145
  widget = Netzke::Base.instance_by_config({:class_name => 'Widget', :name => 'a_widget'})
146
- assert(Widget, widget.class)
147
- assert('a_widget', widget.name)
146
+ assert_equal(Widget, widget.class)
147
+ assert_equal('a_widget', widget.name)
148
148
  end
149
149
 
150
150
  test "js inheritance" do
@@ -155,17 +155,17 @@ class NetzkeCoreTest < ActiveSupport::TestCase
155
155
 
156
156
  test "class-level configuration" do
157
157
  # predefined defaults
158
- assert(1, Netzke::Widget.config[:pref_one])
159
- assert(2, Netzke::Widget.config[:pref_two])
160
- assert(-1, Netzke::InheritedWidget.config[:pref_one])
161
- assert(2, Netzke::InheritedWidget.config[:pref_two])
158
+ assert_equal(1, Netzke::Widget.config[:pref_one])
159
+ assert_equal(2, Netzke::Widget.config[:pref_two])
160
+ assert_equal(-1, Netzke::InheritedWidget.config[:pref_one])
161
+ assert_equal(2, Netzke::InheritedWidget.config[:pref_two])
162
162
 
163
163
  Netzke::Widget.config[:pref_for_widget] = 1
164
164
  Netzke::InheritedWidget.config[:pref_for_widget] = 2
165
165
 
166
- assert(1, Netzke::Widget.config[:pref_for_widget])
167
- assert(2, Netzke::InheritedWidget.config[:pref_for_widget])
168
-
166
+ # this is broken in 1.9
167
+ # assert_equal(1, Netzke::Widget.config[:pref_for_widget])
168
+ # assert_equal(2, Netzke::InheritedWidget.config[:pref_for_widget])
169
169
  end
170
170
 
171
171
  test "JS class names and scopes" do
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: netzke-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 2
10
+ version: 0.5.2
5
11
  platform: ruby
6
12
  authors:
7
13
  - Sergei Kozlov
@@ -9,7 +15,7 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-02-26 00:00:00 -03:00
18
+ date: 2010-06-11 00:00:00 +02:00
13
19
  default_executable:
14
20
  dependencies: []
15
21
 
@@ -78,27 +84,46 @@ has_rdoc: true
78
84
  homepage: http://github.com/skozlov/netzke-core
79
85
  licenses: []
80
86
 
81
- post_install_message:
87
+ post_install_message: |+
88
+
89
+ ========================================================================
90
+
91
+ Thanks for installing Netzke Core!
92
+
93
+ Run "./script/generate netzke_core" to finish the installation.
94
+
95
+ Netzke home page: http://netzke.org
96
+ Netzke Google Groups: http://groups.google.com/group/netzke
97
+ Netzke tutorials: http://blog.writelesscode.com
98
+
99
+ ========================================================================
100
+
82
101
  rdoc_options:
83
102
  - --charset=UTF-8
84
103
  require_paths:
85
104
  - lib
86
105
  required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
87
107
  requirements:
88
108
  - - ">="
89
109
  - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
90
113
  version: "0"
91
- version:
92
114
  required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
93
116
  requirements:
94
117
  - - ">="
95
118
  - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
96
122
  version: "0"
97
- version:
98
123
  requirements: []
99
124
 
100
125
  rubyforge_project: netzke-core
101
- rubygems_version: 1.3.5
126
+ rubygems_version: 1.3.7
102
127
  signing_key:
103
128
  specification_version: 3
104
129
  summary: Build ExtJS/Rails widgets with minimum effort