netzke-core 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/Manifest +2 -0
- data/css/core.css +8 -0
- data/generators/netzke_core/templates/create_netzke_preferences.rb +1 -1
- data/javascripts/core.js +21 -1
- data/lib/app/controllers/netzke_controller.rb +9 -0
- data/lib/app/models/netzke_layout.rb +0 -49
- data/lib/app/models/netzke_preference.rb +6 -6
- data/lib/netzke/action_view_ext.rb +1 -0
- data/lib/netzke/base.rb +64 -56
- data/lib/netzke/controller_extensions.rb +12 -2
- data/lib/netzke/feedback_ghost.rb +43 -0
- data/lib/netzke/js_class_builder.rb +116 -76
- data/lib/netzke-core.rb +16 -8
- data/netzke-core.gemspec +4 -4
- data/test/netzke_core_test.rb +11 -10
- metadata +5 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
v0.2.0
|
2
|
+
* Some re-factoring and redesign. Now simple compound widgets can be created on the fly in the controller
|
3
|
+
* Added ext_widget[:quiet] configuration option to suppress widget's feedback
|
4
|
+
* Support for extra CSS sources, similar to JS
|
5
|
+
* NETZKE_BOOT_CONFIG introduced to specify which Netzke functionality should be disabled to reduce the size of /netzke/netzke.[js|css]
|
6
|
+
* FeedbackGhost widget added - invisible widget providing feedback to the user
|
7
|
+
* netzke_widget controller class-method renamed into netzke
|
8
|
+
* JS-comments now get stripped also from the extra files that get included in the netzke-* gems.
|
9
|
+
* Permissions joined js_config
|
10
|
+
|
11
|
+
Bug fixes
|
12
|
+
|
1
13
|
v0.1.4
|
2
14
|
Helpers added to facilitate ExtJS/netzke.js inclusion
|
3
15
|
The route defined for netzke_controller
|
data/Manifest
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
CHANGELOG
|
2
|
+
css/core.css
|
2
3
|
generators/netzke_core/netzke_core_generator.rb
|
3
4
|
generators/netzke_core/templates/create_netzke_layouts.rb
|
4
5
|
generators/netzke_core/templates/create_netzke_preferences.rb
|
@@ -13,6 +14,7 @@ lib/netzke/action_view_ext.rb
|
|
13
14
|
lib/netzke/base.rb
|
14
15
|
lib/netzke/controller_extensions.rb
|
15
16
|
lib/netzke/core_ext.rb
|
17
|
+
lib/netzke/feedback_ghost.rb
|
16
18
|
lib/netzke/js_class_builder.rb
|
17
19
|
lib/netzke/routing.rb
|
18
20
|
lib/netzke-core.rb
|
data/css/core.css
ADDED
data/javascripts/core.js
CHANGED
@@ -49,7 +49,8 @@ Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
|
|
49
49
|
// Methods common to all widget classes
|
50
50
|
Ext.widgetMixIn = {
|
51
51
|
widgetInit:function(config){
|
52
|
-
this.app = Ext.getCmp('
|
52
|
+
this.app = Ext.getCmp('feedback_ghost');
|
53
|
+
// this.app = Ext.getCmp('application');
|
53
54
|
if (config.tools) Ext.each(config.tools, function(i){i.on.click = this[i.on.click].createDelegate(this)}, this);
|
54
55
|
if (config.actions) Ext.each(config.actions, function(i){i.handler = this[i.handler].createDelegate(this);}, this);
|
55
56
|
},
|
@@ -67,6 +68,7 @@ Ext.widgetMixIn = {
|
|
67
68
|
},
|
68
69
|
|
69
70
|
feedback:function(msg){
|
71
|
+
if (this.initialConfig.quiet) return false;
|
70
72
|
if (this.app && !!this.app.showFeedback) {
|
71
73
|
this.app.showFeedback(msg)
|
72
74
|
} else {
|
@@ -127,3 +129,21 @@ Ext.override(Ext.Panel, {
|
|
127
129
|
|
128
130
|
}
|
129
131
|
});
|
132
|
+
|
133
|
+
// Some Rubyish String extensions
|
134
|
+
// from http://code.google.com/p/inflection-js/
|
135
|
+
String.prototype.capitalize=function()
|
136
|
+
{
|
137
|
+
var str=this.toLowerCase();
|
138
|
+
str=str.substring(0,1).toUpperCase()+str.substring(1);
|
139
|
+
return str;
|
140
|
+
};
|
141
|
+
|
142
|
+
String.prototype.humanize=function(lowFirstLetter)
|
143
|
+
{
|
144
|
+
var str=this.toLowerCase();
|
145
|
+
str=str.replace(new RegExp('_id','g'),'');
|
146
|
+
str=str.replace(new RegExp('_','g'),' ');
|
147
|
+
if(!lowFirstLetter)str=str.capitalize();
|
148
|
+
return str;
|
149
|
+
};
|
@@ -9,6 +9,15 @@ class NetzkeController < ActionController::Base
|
|
9
9
|
f = File.new(path)
|
10
10
|
res << f.read
|
11
11
|
end
|
12
|
+
render :text => res.strip_js_comments
|
13
|
+
}
|
14
|
+
|
15
|
+
format.css {
|
16
|
+
res = ""
|
17
|
+
Netzke::Base.config[:css].each do |path|
|
18
|
+
f = File.new(path)
|
19
|
+
res << f.read
|
20
|
+
end
|
12
21
|
render :text => res
|
13
22
|
}
|
14
23
|
end
|
@@ -1,9 +1,4 @@
|
|
1
1
|
class NetzkeLayout < ActiveRecord::Base
|
2
|
-
# has_many :layout_items#, :class_name => "ExtWidget::LayoutItem", :order => :position
|
3
|
-
# has_many :objects, :class_name => "Objects", :foreign_key => "class_name_id"
|
4
|
-
# belongs_to :role
|
5
|
-
# belongs_to :user
|
6
|
-
|
7
2
|
UNRELATED_ATTRS = %w(created_at updated_at position layout_id)
|
8
3
|
|
9
4
|
def self.user_id
|
@@ -14,16 +9,6 @@ class NetzkeLayout < ActiveRecord::Base
|
|
14
9
|
items_class.constantize.find_all_by_layout_id(id, :order => 'position')
|
15
10
|
end
|
16
11
|
|
17
|
-
#
|
18
|
-
# def self.user_id=(user_id)
|
19
|
-
# @@user_id = user_id
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
# def self.layout_items(widget_name)
|
23
|
-
# layout = self.layout(widget_name)
|
24
|
-
# layout.nil? ? nil : layout.layout_items.map(&:attributes).map{|item| item.delete_if{|k,v| UNRELATED_ATTRS.include?(k)}}
|
25
|
-
# end
|
26
|
-
#
|
27
12
|
def self.by_widget(widget_name)
|
28
13
|
self.find(:first, :conditions => {:widget_name => widget_name, :user_id => self.user_id})
|
29
14
|
end
|
@@ -34,42 +19,8 @@ class NetzkeLayout < ActiveRecord::Base
|
|
34
19
|
layout_item.insert_at(new_index + 1)
|
35
20
|
end
|
36
21
|
|
37
|
-
# def self.layout_items(widget_name)
|
38
|
-
# layout = self.by_widget(widget_name)
|
39
|
-
# if layout
|
40
|
-
# layout.layout_items
|
41
|
-
# else
|
42
|
-
# # create new layout and fill it out with default values
|
43
|
-
# layout = Layout.create({:widget_name => widget_name, :user_id => self.user_id})
|
44
|
-
# end
|
45
|
-
# end
|
46
|
-
|
47
22
|
def items_hash
|
48
23
|
layout_items.map(&:attributes).map{|item| item.delete_if{|k,v| UNRELATED_ATTRS.include?(k)}}.map{ |i| i.convert_keys{ |k| k.to_sym } }
|
49
24
|
end
|
50
|
-
|
51
|
-
# if layout items are provided, use them instead of defaults (exsposed) layout items, but merge their configs with the default
|
52
|
-
# def self.create_layout_for_widget(widget_name, data_class_name, layout_item_class_name, items = nil)
|
53
|
-
# layout = self.create(:widget_name => widget_name, :items_class => layout_item_class_name, :user_id => self.user_id)
|
54
|
-
# data_class = data_class_name.constantize
|
55
|
-
# layout_item_class = layout_item_class_name.constantize
|
56
|
-
#
|
57
|
-
#
|
58
|
-
# if items.nil?
|
59
|
-
# complete_items = data_class.exposed_columns
|
60
|
-
# else
|
61
|
-
# # normalize columns
|
62
|
-
# columns = columns.
|
63
|
-
# default_columns = data_class.exposed_columns.map{|c| c.is_a?(Symbol) ? {:name => c} : c}
|
64
|
-
# columns.each
|
65
|
-
#
|
66
|
-
# complete_columns = columns.nil? ? : columns
|
67
|
-
# complete_columns.each do |c|
|
68
|
-
# config = c.is_a?(Hash) ? c : {:name => c}
|
69
|
-
# # we have to merge layout_id in order to have :position set up properly
|
70
|
-
# item = layout_item_class.create_with_defaults(config.merge({:layout_id => layout.id}), data_class)
|
71
|
-
# end
|
72
|
-
# layout
|
73
|
-
# end
|
74
25
|
|
75
26
|
end
|
@@ -9,12 +9,12 @@ class NetzkePreference < ActiveRecord::Base
|
|
9
9
|
@@user ||= nil
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.
|
13
|
-
@@
|
12
|
+
def self.widget_name=(value)
|
13
|
+
@@widget_name = value
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.
|
17
|
-
@@
|
16
|
+
def self.widget_name
|
17
|
+
@@widget_name ||= nil
|
18
18
|
end
|
19
19
|
|
20
20
|
def normalized_value
|
@@ -48,7 +48,7 @@ class NetzkePreference < ActiveRecord::Base
|
|
48
48
|
|
49
49
|
def self.[](pref_name)
|
50
50
|
pref_name = pref_name.to_s
|
51
|
-
conditions = {:name => pref_name, :user_id => self.user, :
|
51
|
+
conditions = {:name => pref_name, :user_id => self.user, :widget_name => self.widget_name}
|
52
52
|
pref = self.find(:first, :conditions => conditions)
|
53
53
|
# pref = @@user.nil? ? self.find_by_name(pref_name) : self.find_by_name_and_user_id(pref_name, @@user.id)
|
54
54
|
pref && pref.normalized_value
|
@@ -56,7 +56,7 @@ class NetzkePreference < ActiveRecord::Base
|
|
56
56
|
|
57
57
|
def self.[]=(pref_name, new_value)
|
58
58
|
pref_name = pref_name.to_s
|
59
|
-
conditions = {:name => pref_name, :user_id => self.user, :
|
59
|
+
conditions = {:name => pref_name, :user_id => self.user, :widget_name => self.widget_name}
|
60
60
|
pref = self.find(:first, :conditions => conditions) || self.create(conditions)
|
61
61
|
# pref = self.user.nil? ? self.find_or_create_by_name(pref_name) : self.find_or_create_by_name_and_user_id(pref_name, self.user.id)
|
62
62
|
pref.normalized_value = new_value
|
@@ -18,6 +18,7 @@ module Netzke
|
|
18
18
|
def netzke_css_include(theme_name = :default)
|
19
19
|
res = stylesheet_link_tag("/extjs/resources/css/ext-all.css")
|
20
20
|
res << stylesheet_link_tag("/extjs/resources/css/xtheme-#{theme_name}.css") unless theme_name == :default
|
21
|
+
res << stylesheet_link_tag("/netzke/netzke.css") # CSS from Netzke
|
21
22
|
res
|
22
23
|
end
|
23
24
|
end
|
data/lib/netzke/base.rb
CHANGED
@@ -1,35 +1,78 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
3
|
module Netzke
|
4
|
+
#
|
5
|
+
# Configuration:
|
6
|
+
# * Define NETZKE_BOOT_CONFIG in environment.rb to specify which Netzke functionality should be disabled
|
7
|
+
# to reduce the size of /netzke/netzke.[js|css]. Those Netzke gems that use additional JS-code
|
8
|
+
# should be aware of this constant.
|
9
|
+
#
|
4
10
|
class Base
|
5
|
-
# client-side code (generates JS-classes of the widgets)
|
6
|
-
include Netzke::JsClassBuilder
|
7
|
-
|
8
|
-
# Global Netzke configuration
|
9
|
-
def self.config
|
10
|
-
@@config ||= {
|
11
|
-
:javascripts => ["#{File.dirname(__FILE__)}/../../javascripts/core.js"] # locations of javascript files (which automatically will be collected into one file and sent as netzke.js)
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.js_class_code(cached_dependencies = [])
|
16
|
-
self.new(:js_class => true).js_missing_code(cached_dependencies)
|
17
|
-
end
|
18
|
-
|
19
11
|
# Helper class to read/write from/to widget's persistent preferences. TODO: rework it.
|
20
12
|
class Config
|
21
13
|
def initialize(widget_name)
|
22
14
|
@widget_name = widget_name
|
23
15
|
end
|
24
16
|
def []=(k,v)
|
25
|
-
NetzkePreference.
|
17
|
+
NetzkePreference.widget_name = @widget_name
|
26
18
|
NetzkePreference[k] = v
|
27
19
|
end
|
28
20
|
def [](k)
|
29
|
-
NetzkePreference.
|
21
|
+
NetzkePreference.widget_name = @widget_name
|
30
22
|
NetzkePreference[k]
|
31
23
|
end
|
32
24
|
end
|
25
|
+
|
26
|
+
# Client-side code (generates JS-class of the widget)
|
27
|
+
include Netzke::JsClassBuilder
|
28
|
+
|
29
|
+
# Class methods
|
30
|
+
class << self
|
31
|
+
# Global Netzke configuration
|
32
|
+
def config
|
33
|
+
@@config ||= {
|
34
|
+
# locations of javascript and css files (which will be automatically collected into one file and sent as /netzke/netzke.js and /netzke/netzke.css respectively)
|
35
|
+
:javascripts => [],
|
36
|
+
:css => []
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def short_widget_class_name
|
41
|
+
name.split("::").last
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Use this class method to declare connection points between client side of a widget and its server side. A method in a widget class with the same name will be (magically) called by the client side of the widget. See Grid widget for an example
|
46
|
+
#
|
47
|
+
def interface(*interface_points)
|
48
|
+
interfacep = read_inheritable_attribute(:interface_points) || []
|
49
|
+
interface_points.each{|p| interfacep << p}
|
50
|
+
write_inheritable_attribute(:interface_points, interfacep)
|
51
|
+
|
52
|
+
interface_points.each do |interfacep|
|
53
|
+
module_eval <<-END, __FILE__, __LINE__
|
54
|
+
def interface_#{interfacep}(*args)
|
55
|
+
#{interfacep}(*args).to_js
|
56
|
+
end
|
57
|
+
# FIXME: commented out because otherwise ColumnOperations stop working
|
58
|
+
# def #{interfacep}(*args)
|
59
|
+
# flash :warning => "API point '#{interfacep}' is not implemented for widget '#{short_widget_class_name}'"
|
60
|
+
# {:flash => @flash}
|
61
|
+
# end
|
62
|
+
END
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def interface_points
|
67
|
+
read_inheritable_attribute(:interface_points)
|
68
|
+
end
|
69
|
+
|
70
|
+
# returns an instance of a widget defined in the config
|
71
|
+
def instance_by_config(config)
|
72
|
+
widget_class = "Netzke::#{config[:widget_class_name]}".constantize
|
73
|
+
widget_class.new(config)
|
74
|
+
end
|
75
|
+
end
|
33
76
|
|
34
77
|
attr_accessor :config, :server_confg, :parent, :logger, :id_name, :permissions
|
35
78
|
attr_reader :pref
|
@@ -57,47 +100,13 @@ module Netzke
|
|
57
100
|
self.class.short_widget_class_name
|
58
101
|
end
|
59
102
|
|
60
|
-
|
61
|
-
name.split("::").last
|
62
|
-
end
|
63
|
-
|
64
|
-
#
|
65
|
-
# Use this class-method to declare connection points between client side of a widget and its server side. A method in a widget class with the same name will be (magically) called by the client-side of the widget. See Grid widget for an example
|
66
|
-
#
|
67
|
-
def self.interface(*interface_points)
|
68
|
-
interfacep = read_inheritable_attribute(:interface_points) || []
|
69
|
-
interface_points.each{|p| interfacep << p}
|
70
|
-
write_inheritable_attribute(:interface_points, interfacep)
|
71
|
-
|
72
|
-
interface_points.each do |interfacep|
|
73
|
-
module_eval <<-END, __FILE__, __LINE__
|
74
|
-
def interface_#{interfacep}(*args)
|
75
|
-
#{interfacep}(*args).to_js
|
76
|
-
end
|
77
|
-
# FIXME: commented out because otherwise ColumnOperations stop working
|
78
|
-
# def #{interfacep}(*args)
|
79
|
-
# flash :warning => "API point '#{interfacep}' is not implemented for widget '#{short_widget_class_name}'"
|
80
|
-
# {:flash => @flash}
|
81
|
-
# end
|
82
|
-
END
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.interface_points
|
87
|
-
read_inheritable_attribute(:interface_points)
|
88
|
-
end
|
89
|
-
|
90
|
-
def interface_points
|
91
|
-
self.class.interface_points
|
92
|
-
end
|
93
|
-
|
94
|
-
interface :get_widget # default
|
103
|
+
interface :get_widget # every widget gets this
|
95
104
|
|
96
105
|
## Dependencies
|
97
106
|
def dependencies
|
98
107
|
@dependencies ||= begin
|
99
|
-
non_late_aggregatees_widget_classes =
|
100
|
-
(initial_dependencies + non_late_aggregatees_widget_classes).uniq
|
108
|
+
non_late_aggregatees_widget_classes = non_late_aggregatees.values.map{|v| v[:widget_class_name]}
|
109
|
+
(initial_dependencies + non_late_aggregatees_widget_classes << self.class.short_widget_class_name).uniq
|
101
110
|
end
|
102
111
|
end
|
103
112
|
|
@@ -123,7 +132,7 @@ module Netzke
|
|
123
132
|
aggregatees.merge!(aggr)
|
124
133
|
end
|
125
134
|
|
126
|
-
# The difference between aggregatees and late aggregatees is the following: the former gets instantiated together with its aggregator and is normally instantly visible as a part of it.
|
135
|
+
# The difference between aggregatees and late aggregatees is the following: the former gets instantiated together with its aggregator and is normally *instantly* visible as a part of it (for example, the widget in the initially expanded panel in an Accordion). A late aggregatee doesn't get instantiated along with its aggregator. Until it gets requested from the server, it doesn't take any part in its aggregator's life. An example of late aggregatee could be a widget that is loaded dynamically into a previously collapsed panel of an Accordion, or a preferences window (late aggregatee) for a widget (aggregator) that only gets shown when user wants to edit widget's preferences.
|
127
136
|
def initial_late_aggregatees
|
128
137
|
{}
|
129
138
|
end
|
@@ -145,7 +154,6 @@ module Netzke
|
|
145
154
|
aggregator
|
146
155
|
end
|
147
156
|
|
148
|
-
|
149
157
|
def full_widget_class_name(short_name)
|
150
158
|
"Netzke::#{short_name}"
|
151
159
|
end
|
@@ -178,7 +186,7 @@ module Netzke
|
|
178
186
|
config[:allow] && config[:allow].each{|p| @permissions.merge!(p.to_sym => true)} # allow
|
179
187
|
|
180
188
|
# ... and then merge it with NetzkePreferences (if not instantiated to only generate JS-class code)
|
181
|
-
|
189
|
+
available_permissions.each do |p|
|
182
190
|
@permissions[p.to_sym] = @pref["permissions.#{p}"] if !@pref["permissions.#{p}"].nil?
|
183
191
|
end
|
184
192
|
end
|
@@ -36,7 +36,7 @@ module Netzke
|
|
36
36
|
#
|
37
37
|
# Use this method to declare a widget in the controller
|
38
38
|
#
|
39
|
-
def
|
39
|
+
def netzke(name, config={})
|
40
40
|
# which module is the widget?
|
41
41
|
config[:widget_class_name] ||= name.to_s.classify
|
42
42
|
config[:name] ||= name
|
@@ -61,7 +61,7 @@ module Netzke
|
|
61
61
|
widget_instance.js_widget_instance
|
62
62
|
end
|
63
63
|
|
64
|
-
def #{name}
|
64
|
+
def #{name}_class_definition_old
|
65
65
|
result = ""
|
66
66
|
config = controller.class.widget_config_storage[:#{name}]
|
67
67
|
@generated_widget_classes ||= []
|
@@ -72,6 +72,16 @@ module Netzke
|
|
72
72
|
end
|
73
73
|
result
|
74
74
|
end
|
75
|
+
|
76
|
+
def #{name}_class_definition
|
77
|
+
@generated_widget_classes ||= []
|
78
|
+
config = controller.class.widget_config_storage[:#{name}]
|
79
|
+
widget_instance = Netzke::#{config[:widget_class_name]}.new(config)
|
80
|
+
res = widget_instance.js_missing_code(@generated_widget_classes)
|
81
|
+
@generated_widget_classes += widget_instance.dependencies
|
82
|
+
@generated_widget_classes.uniq!
|
83
|
+
res
|
84
|
+
end
|
75
85
|
END_EVAL
|
76
86
|
|
77
87
|
# add controller action which will render a simple HTML page containing the widget
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Netzke
|
2
|
+
#
|
3
|
+
# An invisible component that provides feedback service for all Netzke widgets
|
4
|
+
#
|
5
|
+
class FeedbackGhost < Base
|
6
|
+
class << self
|
7
|
+
def js_base_class
|
8
|
+
"Ext.Component" # yes, invisible
|
9
|
+
end
|
10
|
+
|
11
|
+
def js_extend_properties
|
12
|
+
{
|
13
|
+
:show_feedback => <<-JS.l,
|
14
|
+
function(msg){
|
15
|
+
var createBox = function(s, l){
|
16
|
+
return ['<div class="msg">',
|
17
|
+
'<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>',
|
18
|
+
'<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">', s, '</div></div></div>',
|
19
|
+
'<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>',
|
20
|
+
'</div>'].join('');
|
21
|
+
}
|
22
|
+
|
23
|
+
var showBox = function(msg, lvl){
|
24
|
+
if (!lvl) lvl = 'notice';
|
25
|
+
var msgCt = Ext.DomHelper.insertFirst(document.body, {class:'netzke-feedback'}, true);
|
26
|
+
var m = Ext.DomHelper.append(msgCt, {html:createBox(msg,lvl)}, true);
|
27
|
+
m.slideIn('t').pause(2).ghost("b", {remove:true});
|
28
|
+
}
|
29
|
+
|
30
|
+
if (typeof msg != 'string') {
|
31
|
+
Ext.each(msg, function(m){
|
32
|
+
showBox(m.msg, m.level)
|
33
|
+
})
|
34
|
+
} else {
|
35
|
+
showBox(msg)
|
36
|
+
}
|
37
|
+
}
|
38
|
+
JS
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -5,110 +5,150 @@ module Netzke
|
|
5
5
|
# Most of the methods below are meant to be overwritten by a concrete widget class.
|
6
6
|
#
|
7
7
|
module JsClassBuilder
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# widget's actions that are loaded at the moment of instantiating a widget
|
12
|
-
def actions; null; end
|
13
|
-
|
14
|
-
# widget's tools that are loaded at the moment of instantiating a widget see (js_config method)
|
15
|
-
def tools; []; end
|
16
|
-
|
17
|
-
def tbar; null; end
|
18
|
-
|
19
|
-
def bbar; null; end
|
20
|
-
|
21
|
-
# functions and properties that will be used to extend the functionality of (Ext) JS-class specified in js_base_class
|
22
|
-
def js_extend_properties; {}; end
|
23
|
-
|
24
|
-
# code executed before and after the constructor
|
25
|
-
def js_before_constructor; ""; end
|
26
|
-
def js_after_constructor; ""; end
|
27
|
-
|
28
|
-
# widget's listeners
|
29
|
-
def js_listeners; {}; end
|
30
|
-
|
31
|
-
# widget's menus
|
32
|
-
def js_menus; []; end
|
33
|
-
|
34
|
-
# items
|
35
|
-
def js_items; null; end
|
36
|
-
|
37
|
-
# default config that is passed into the constructor
|
38
|
-
def js_default_config
|
39
|
-
{
|
40
|
-
:title => short_widget_class_name,
|
41
|
-
:listeners => js_listeners,
|
42
|
-
:tools => "config.tools".l,
|
43
|
-
:actions => "config.actions".l,
|
44
|
-
:tbar => "config.tbar".l,
|
45
|
-
:bbar => "config.bbar".l,
|
46
|
-
:items => js_items,
|
47
|
-
:height => 400,
|
48
|
-
:width => 800,
|
49
|
-
:border => false
|
50
|
-
}
|
8
|
+
def self.included(base)
|
9
|
+
base.extend ClassMethods
|
51
10
|
end
|
52
11
|
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
Ext.componentCache['#{short_widget_class_name}'] = Ext.extend(#{js_base_class}, Ext.chainApply([Ext.widgetMixIn, {
|
57
|
-
constructor: function(config){
|
58
|
-
this.widgetInit(config);
|
59
|
-
#{js_before_constructor}
|
60
|
-
Ext.componentCache['#{short_widget_class_name}'].superclass.constructor.call(this, Ext.apply(#{js_default_config.to_js}, config));
|
61
|
-
#{js_after_constructor}
|
62
|
-
this.setEvents();
|
63
|
-
this.addMenus(#{js_menus.to_js});
|
64
|
-
}
|
65
|
-
}, #{js_extend_properties.to_js}]))
|
66
|
-
JS
|
67
|
-
end
|
12
|
+
#
|
13
|
+
# Instance methods
|
14
|
+
#
|
68
15
|
|
69
|
-
#
|
70
|
-
def js_widget_instance
|
71
|
-
%Q(var #{config[:name].to_js} = new Ext.componentCache['#{short_widget_class_name}'](#{js_config.to_js});)
|
72
|
-
end
|
73
|
-
|
74
|
-
# the config that is send from the server and is used for instantiating a widget
|
16
|
+
# The config that is sent from the server and is used for instantiating a widget
|
75
17
|
def js_config
|
76
18
|
res = {}
|
77
|
-
|
78
|
-
# recursively include configs of all (non-late) aggregatees, so that the widget can instantiate them
|
19
|
+
|
20
|
+
# recursively include configs of all (non-late) aggregatees, so that the widget can instantiate them
|
79
21
|
aggregatees.each_pair do |aggr_name, aggr_config|
|
80
22
|
next if aggr_config[:late_aggregation]
|
81
23
|
res["#{aggr_name}_config".to_sym] = aggregatee_instance(aggr_name.to_sym).js_config
|
82
24
|
end
|
83
|
-
|
25
|
+
|
84
26
|
# interface
|
85
|
-
interface = interface_points.inject({}){|h,interfacep| h.merge(interfacep => widget_action(interfacep))}
|
27
|
+
interface = self.class.interface_points.inject({}){|h,interfacep| h.merge(interfacep => widget_action(interfacep))}
|
86
28
|
res.merge!(:interface => interface)
|
87
|
-
|
29
|
+
|
88
30
|
res.merge!(:widget_class_name => short_widget_class_name)
|
89
31
|
|
90
32
|
res.merge!(config[:ext_config])
|
91
33
|
res.merge!(:id => @id_name)
|
92
|
-
|
34
|
+
|
93
35
|
# include tools and actions
|
94
|
-
res.merge!(:tools => tools)
|
95
|
-
res.merge!(:actions => actions)
|
36
|
+
res.merge!(:tools => tools) if tools
|
37
|
+
res.merge!(:actions => actions) if actions
|
38
|
+
res.merge!(:bbar => tbar) if tbar
|
39
|
+
res.merge!(:tbar => bbar) if bbar
|
40
|
+
|
41
|
+
# include permissions
|
42
|
+
res.merge!(:permissions => permissions) unless available_permissions.empty?
|
43
|
+
|
44
|
+
# include eventual region_config
|
45
|
+
res.merge!(:region_config => config[:region_config])
|
96
46
|
res
|
97
47
|
end
|
48
|
+
|
49
|
+
# Generate instantiating - used when a widget is generated stand-alone (as a part of a HTML page)
|
50
|
+
def js_widget_instance
|
51
|
+
%Q(var #{config[:name].to_js} = new Ext.componentCache['#{short_widget_class_name}'](#{js_config.to_js});)
|
52
|
+
end
|
98
53
|
|
99
|
-
#
|
54
|
+
# All the JS-code required by this *instance* of the widget. It includes the JS-class for the widget
|
55
|
+
# itself, as well as JS-classes for all widgets (non-late) aggregatees.
|
100
56
|
def js_missing_code(cached_dependencies = [])
|
101
57
|
result = ""
|
102
58
|
dependencies.each do |dep_name|
|
103
|
-
|
104
|
-
|
59
|
+
unless cached_dependencies.include?(dep_name)
|
60
|
+
dependency_class = "Netzke::#{dep_name}".constantize
|
61
|
+
result << dependency_class.js_class
|
62
|
+
end
|
105
63
|
end
|
106
|
-
result << js_class.strip_js_comments unless cached_dependencies.include?(short_widget_class_name) && !config[:no_caching]
|
107
64
|
result
|
108
65
|
end
|
109
66
|
|
67
|
+
# widget's actions, tools and toolbars that are loaded at the moment of instantiating a widget
|
68
|
+
def actions; nil; end
|
69
|
+
def tools; nil; end
|
70
|
+
def tbar; nil; end
|
71
|
+
def bbar; nil; end
|
72
|
+
|
110
73
|
# little helpers
|
111
74
|
def this; "this".l; end
|
112
75
|
def null; "null".l; end
|
76
|
+
|
77
|
+
|
78
|
+
# Methods used to create the javascript class (only once per widget class).
|
79
|
+
# The generated code gets cached at the browser, and the widget intstances (at the browser side)
|
80
|
+
# get instantiated from it.
|
81
|
+
# All these methods can be overwritten in case you want to extend the functionality of some pre-built widget
|
82
|
+
# instead of using it as is (using both would cause JS-code duplication)
|
83
|
+
module ClassMethods
|
84
|
+
# the JS (Ext) class that we inherit from on JS-level
|
85
|
+
def js_base_class; "Ext.Panel"; end
|
86
|
+
|
87
|
+
# functions and properties that will be used to extend the functionality of (Ext) JS-class specified in js_base_class
|
88
|
+
def js_extend_properties; {}; end
|
89
|
+
|
90
|
+
# code executed before and after the constructor
|
91
|
+
def js_before_constructor; ""; end
|
92
|
+
def js_after_constructor; ""; end
|
93
|
+
|
94
|
+
# widget's listeners
|
95
|
+
def js_listeners; {}; end
|
96
|
+
|
97
|
+
# widget's menus
|
98
|
+
def js_menus; []; end
|
99
|
+
|
100
|
+
# items
|
101
|
+
def js_items; null; end
|
102
|
+
|
103
|
+
# default config that is always passed into the constructor
|
104
|
+
def js_default_config
|
105
|
+
{
|
106
|
+
:title => "config.id.humanize()".l,
|
107
|
+
:listeners => js_listeners,
|
108
|
+
:tools => "config.tools".l,
|
109
|
+
:actions => "config.actions".l,
|
110
|
+
:tbar => "config.tbar".l,
|
111
|
+
:bbar => "config.bbar".l,
|
112
|
+
# :items => "config.items".l,
|
113
|
+
# :items => js_items,
|
114
|
+
:height => 400,
|
115
|
+
:width => 800,
|
116
|
+
:border => false
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
# Declaration of widget's class (stored in the cache storage (Ext.componentCache) at the client side
|
121
|
+
# to be reused at the moment of widget instantiation)
|
122
|
+
def js_class
|
123
|
+
<<-JS
|
124
|
+
Ext.componentCache['#{short_widget_class_name}'] = Ext.extend(#{js_base_class}, Ext.chainApply([Ext.widgetMixIn, {
|
125
|
+
constructor: function(config){
|
126
|
+
this.widgetInit(config);
|
127
|
+
#{js_before_constructor}
|
128
|
+
Ext.componentCache['#{short_widget_class_name}'].superclass.constructor.call(this, Ext.apply(#{js_default_config.to_js}, config));
|
129
|
+
#{js_after_constructor}
|
130
|
+
this.setEvents();
|
131
|
+
this.addMenus(#{js_menus.to_js});
|
132
|
+
}
|
133
|
+
}, #{js_extend_properties.to_js}]))
|
134
|
+
JS
|
135
|
+
end
|
136
|
+
|
137
|
+
# class definition of the widget plus that of all the dependencies, minus those that are specified as cached_dependencies
|
138
|
+
def js_missing_code(cached_dependencies = [])
|
139
|
+
result = ""
|
140
|
+
dependencies.each do |dep_name|
|
141
|
+
dependency_class = "Netzke::#{dep_name}".constantize
|
142
|
+
result << dependency_class.js_class_code(cached_dependencies)
|
143
|
+
end
|
144
|
+
result << js_class.strip_js_comments unless cached_dependencies.include?(short_widget_class_name) && !config[:no_caching]
|
145
|
+
result
|
146
|
+
end
|
147
|
+
|
148
|
+
def this; "this".l; end
|
149
|
+
def null; "null".l; end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
113
153
|
end
|
114
154
|
end
|
data/lib/netzke-core.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# NetzkeCore
|
2
2
|
require 'netzke/js_class_builder'
|
3
3
|
require 'netzke/base'
|
4
|
+
require 'netzke/feedback_ghost'
|
4
5
|
require 'netzke/action_view_ext'
|
5
6
|
require 'netzke/controller_extensions'
|
6
7
|
require 'netzke/core_ext'
|
@@ -17,19 +18,26 @@ require 'vendor/facets/hash/recursive_merge'
|
|
17
18
|
ActiveSupport::Dependencies.load_once_paths.delete(path)
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
if defined? ActionController
|
22
|
+
# Provide controllers with netzke class method
|
23
|
+
ActionController::Base.class_eval do
|
24
|
+
include Netzke::ControllerExtensions
|
25
|
+
end
|
26
|
+
|
27
|
+
# Include the route to netzke controller
|
28
|
+
ActionController::Routing::RouteSet::Mapper.send :include, Netzke::Routing::MapperExtensions
|
23
29
|
end
|
24
30
|
|
31
|
+
if defined? ActionView
|
32
|
+
# Helpers to be put into layouts
|
33
|
+
ActionView::Base.send :include, Netzke::ActionViewExt
|
34
|
+
end
|
35
|
+
|
25
36
|
# Make this plugin auto-reloaded for easier development
|
26
37
|
ActiveSupport::Dependencies.load_once_paths.delete(File.join(File.dirname(__FILE__)))
|
27
38
|
|
28
39
|
# Include the javascript
|
29
40
|
Netzke::Base.config[:javascripts] << "#{File.dirname(__FILE__)}/../javascripts/core.js"
|
30
41
|
|
31
|
-
# Include
|
32
|
-
|
33
|
-
|
34
|
-
# Helpers to be put into layouts
|
35
|
-
ActionView::Base.send :include, Netzke::ActionViewExt
|
42
|
+
# Include CSS
|
43
|
+
Netzke::Base.config[:css] << "#{File.dirname(__FILE__)}/../css/core.css"
|
data/netzke-core.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{netzke-core}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Sergei Kozlov"]
|
9
|
-
s.date = %q{2009-01-
|
9
|
+
s.date = %q{2009-01-07}
|
10
10
|
s.description = %q{Build ExtJS/Rails widgets with minimum effort}
|
11
11
|
s.email = %q{sergei@writelesscode.com}
|
12
|
-
s.extra_rdoc_files = ["CHANGELOG", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/action_view_ext.rb", "lib/netzke/base.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/js_class_builder.rb", "lib/netzke/routing.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "README.mdown", "tasks/netzke_core_tasks.rake"]
|
13
|
-
s.files = ["CHANGELOG", "generators/netzke_core/netzke_core_generator.rb", "generators/netzke_core/templates/create_netzke_layouts.rb", "generators/netzke_core/templates/create_netzke_preferences.rb", "generators/netzke_core/USAGE", "init.rb", "install.rb", "javascripts/core.js", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/action_view_ext.rb", "lib/netzke/base.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/js_class_builder.rb", "lib/netzke/routing.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "Manifest", "netzke-core.gemspec", "Rakefile", "README.mdown", "tasks/netzke_core_tasks.rake", "test/app_root/app/controllers/application.rb", "test/app_root/config/boot.rb", "test/app_root/config/database.yml", "test/app_root/config/environment.rb", "test/app_root/config/environments/in_memory.rb", "test/app_root/config/environments/mysql.rb", "test/app_root/config/environments/postgresql.rb", "test/app_root/config/environments/sqlite.rb", "test/app_root/config/environments/sqlite3.rb", "test/app_root/config/routes.rb", "test/app_root/script/console", "test/core_ext_test.rb", "test/netzke_core_test.rb", "test/test_helper.rb", "uninstall.rb"]
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/action_view_ext.rb", "lib/netzke/base.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/feedback_ghost.rb", "lib/netzke/js_class_builder.rb", "lib/netzke/routing.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "README.mdown", "tasks/netzke_core_tasks.rake"]
|
13
|
+
s.files = ["CHANGELOG", "css/core.css", "generators/netzke_core/netzke_core_generator.rb", "generators/netzke_core/templates/create_netzke_layouts.rb", "generators/netzke_core/templates/create_netzke_preferences.rb", "generators/netzke_core/USAGE", "init.rb", "install.rb", "javascripts/core.js", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/action_view_ext.rb", "lib/netzke/base.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/feedback_ghost.rb", "lib/netzke/js_class_builder.rb", "lib/netzke/routing.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "Manifest", "netzke-core.gemspec", "Rakefile", "README.mdown", "tasks/netzke_core_tasks.rake", "test/app_root/app/controllers/application.rb", "test/app_root/config/boot.rb", "test/app_root/config/database.yml", "test/app_root/config/environment.rb", "test/app_root/config/environments/in_memory.rb", "test/app_root/config/environments/mysql.rb", "test/app_root/config/environments/postgresql.rb", "test/app_root/config/environments/sqlite.rb", "test/app_root/config/environments/sqlite3.rb", "test/app_root/config/routes.rb", "test/app_root/script/console", "test/core_ext_test.rb", "test/netzke_core_test.rb", "test/test_helper.rb", "uninstall.rb"]
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.homepage = %q{http://writelesscode.com}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Netzke-core", "--main", "README.mdown"]
|
data/test/netzke_core_test.rb
CHANGED
@@ -13,10 +13,6 @@ module Netzke
|
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
16
|
-
# def initial_dependencies
|
17
|
-
# %w{NestedWidgetOne NestedWidgetTwo DeepNestedWidget}
|
18
|
-
# end
|
19
|
-
|
20
16
|
def available_permissions
|
21
17
|
%w(read update)
|
22
18
|
end
|
@@ -123,11 +119,16 @@ class NetzkeCoreTest < ActiveSupport::TestCase
|
|
123
119
|
assert(!widget.dependencies.include?('DeepNestedWidget'))
|
124
120
|
end
|
125
121
|
|
126
|
-
test "dependencies in JS class generators" do
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
122
|
+
# test "dependencies in JS class generators" do
|
123
|
+
# js_code = Widget.js_class
|
124
|
+
# assert(js_code.index("Ext.componentCache['NestedWidgetOne']"))
|
125
|
+
# assert(js_code.index("Ext.componentCache['NestedWidgetTwo']"))
|
126
|
+
# assert(js_code.index("Ext.componentCache['DeepNestedWidget']"))
|
127
|
+
# end
|
128
|
+
|
129
|
+
test "widget instance by config" do
|
130
|
+
widget = Netzke::Base.instance_by_config({:widget_class_name => 'Widget', :name => 'a_widget'})
|
131
|
+
assert(Widget, widget.class)
|
132
|
+
assert('a_widget', widget.config[:name])
|
131
133
|
end
|
132
|
-
|
133
134
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netzke-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergei Kozlov
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-07 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -28,6 +28,7 @@ extra_rdoc_files:
|
|
28
28
|
- lib/netzke/base.rb
|
29
29
|
- lib/netzke/controller_extensions.rb
|
30
30
|
- lib/netzke/core_ext.rb
|
31
|
+
- lib/netzke/feedback_ghost.rb
|
31
32
|
- lib/netzke/js_class_builder.rb
|
32
33
|
- lib/netzke/routing.rb
|
33
34
|
- lib/netzke-core.rb
|
@@ -37,6 +38,7 @@ extra_rdoc_files:
|
|
37
38
|
- tasks/netzke_core_tasks.rake
|
38
39
|
files:
|
39
40
|
- CHANGELOG
|
41
|
+
- css/core.css
|
40
42
|
- generators/netzke_core/netzke_core_generator.rb
|
41
43
|
- generators/netzke_core/templates/create_netzke_layouts.rb
|
42
44
|
- generators/netzke_core/templates/create_netzke_preferences.rb
|
@@ -51,6 +53,7 @@ files:
|
|
51
53
|
- lib/netzke/base.rb
|
52
54
|
- lib/netzke/controller_extensions.rb
|
53
55
|
- lib/netzke/core_ext.rb
|
56
|
+
- lib/netzke/feedback_ghost.rb
|
54
57
|
- lib/netzke/js_class_builder.rb
|
55
58
|
- lib/netzke/routing.rb
|
56
59
|
- lib/netzke-core.rb
|