netzke-basepack 0.4.2 → 0.5.1
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/.autotest +1 -0
- data/.gitignore +6 -0
- data/{CHANGELOG → CHANGELOG.rdoc} +26 -0
- data/README.rdoc +11 -11
- data/Rakefile +37 -11
- data/TODO.rdoc +8 -0
- data/VERSION +1 -0
- data/javascripts/basepack.js +71 -28
- data/lib/app/models/netzke_auto_column.rb +56 -0
- data/lib/netzke-basepack.rb +5 -3
- data/lib/netzke/accordion_panel.rb +69 -67
- data/lib/netzke/active_record/basepack.rb +104 -0
- data/lib/netzke/active_record/data_accessor.rb +33 -0
- data/lib/netzke/basic_app.rb +233 -124
- data/lib/netzke/border_layout_panel.rb +97 -98
- data/lib/netzke/configuration_panel.rb +24 -0
- data/lib/netzke/data_accessor.rb +71 -0
- data/lib/netzke/ext.rb +6 -0
- data/lib/netzke/field_model.rb +1 -1
- data/lib/netzke/fields_configurator.rb +62 -37
- data/lib/netzke/form_panel.rb +161 -51
- data/lib/netzke/form_panel_api.rb +74 -0
- data/lib/netzke/form_panel_js.rb +129 -0
- data/lib/netzke/grid_panel.rb +385 -80
- data/lib/netzke/grid_panel_api.rb +352 -0
- data/lib/netzke/grid_panel_extras/javascripts/rows-dd.js +280 -0
- data/lib/netzke/grid_panel_js.rb +721 -0
- data/lib/netzke/masquerade_selector.rb +53 -0
- data/lib/netzke/panel.rb +9 -0
- data/lib/netzke/plugins/configuration_tool.rb +121 -0
- data/lib/netzke/property_editor.rb +95 -7
- data/lib/netzke/property_editor_extras/helper_model.rb +55 -34
- data/lib/netzke/search_panel.rb +62 -0
- data/lib/netzke/tab_panel.rb +97 -37
- data/lib/netzke/table_editor.rb +49 -44
- data/lib/netzke/tree_panel.rb +15 -16
- data/lib/netzke/wrapper.rb +29 -5
- data/netzke-basepack.gemspec +151 -19
- data/stylesheets/basepack.css +5 -0
- data/test/app_root/app/models/book.rb +1 -1
- data/test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb +1 -1
- data/test/unit/accordion_panel_test.rb +1 -2
- data/test/unit/active_record_basepack_test.rb +54 -0
- data/test/unit/grid_panel_test.rb +8 -12
- data/test/unit/helper_model_test.rb +30 -0
- metadata +69 -78
- data/Manifest +0 -86
- data/TODO +0 -3
- data/lib/app/models/netzke_hash_record.rb +0 -180
- data/lib/app/models/netzke_layout_item.rb +0 -11
- data/lib/netzke/ar_ext.rb +0 -269
- data/lib/netzke/configuration_tool.rb +0 -80
- data/lib/netzke/container.rb +0 -77
- data/lib/netzke/db_fields.rb +0 -44
- data/lib/netzke/fields_configurator_old.rb +0 -62
- data/lib/netzke/form_panel_extras/interface.rb +0 -56
- data/lib/netzke/form_panel_extras/js_builder.rb +0 -134
- data/lib/netzke/grid_panel_extras/interface.rb +0 -206
- data/lib/netzke/grid_panel_extras/js_builder.rb +0 -352
- data/test/unit/ar_ext_test.rb +0 -53
- data/test/unit/netzke_hash_record_test.rb +0 -52
- data/test/unit/netzke_layout_item_test.rb +0 -28
@@ -0,0 +1,104 @@
|
|
1
|
+
module Netzke::ActiveRecord
|
2
|
+
# Provides extensions to all ActiveRecord-based classes
|
3
|
+
module Basepack
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
# Allow nested association access (assocs separated by "." or "__"), e.g.: proxy_service.asset__gui_folder__name
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# Book.first.genre__name = 'Fantasy'
|
12
|
+
#
|
13
|
+
# is the same as:
|
14
|
+
#
|
15
|
+
# Book.first.genre = Genre.find_by_name('Fantasy')
|
16
|
+
#
|
17
|
+
# The result - easier forms and grids that handle nested models: simply specify column/field name as "genre__name".
|
18
|
+
def method_missing(method, *args, &block)
|
19
|
+
# if refering to a column, just pass it to the original method_missing
|
20
|
+
return super if self.class.column_names.include?(method.to_s)
|
21
|
+
|
22
|
+
split = method.to_s.split(/\.|__/)
|
23
|
+
if split.size > 1
|
24
|
+
if split.last =~ /=$/
|
25
|
+
if split.size == 2
|
26
|
+
# search for association and assign it to self
|
27
|
+
assoc = self.class.reflect_on_association(split.first.to_sym)
|
28
|
+
assoc_method = split.last.chop
|
29
|
+
if assoc
|
30
|
+
begin
|
31
|
+
assoc_instance = assoc.klass.send("find_by_#{assoc_method}", *args)
|
32
|
+
rescue NoMethodError
|
33
|
+
assoc_instance = nil
|
34
|
+
logger.debug "!!! no find_by_#{assoc_method} method for class #{assoc.klass.name}\n"
|
35
|
+
end
|
36
|
+
if (assoc_instance)
|
37
|
+
self.send("#{split.first}=", assoc_instance)
|
38
|
+
else
|
39
|
+
logger.debug "!!! Couldn't find association #{split.first} by #{assoc_method} '#{args.first}'"
|
40
|
+
end
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
else
|
48
|
+
res = self
|
49
|
+
split.each do |m|
|
50
|
+
if res.respond_to?(m)
|
51
|
+
res = res.send(m) unless res.nil?
|
52
|
+
else
|
53
|
+
res.nil? ? nil : super
|
54
|
+
end
|
55
|
+
end
|
56
|
+
res
|
57
|
+
end
|
58
|
+
else
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module ClassMethods
|
64
|
+
|
65
|
+
def options_for(column, query = nil)
|
66
|
+
# First, check if we have options for this class and column defined in persistent storage
|
67
|
+
NetzkePreference.widget_name = self.name
|
68
|
+
options = NetzkePreference[:combobox_options] || {}
|
69
|
+
if options[column]
|
70
|
+
options[column].select{ |o| o.index(/^#{query}/) }
|
71
|
+
elsif respond_to?("#{column}_combobox_options")
|
72
|
+
# AR class provides the choices itself
|
73
|
+
send("#{column}_combobox_options", query)
|
74
|
+
else
|
75
|
+
# Returns all unique values for a column, filtered with <tt>query</tt>
|
76
|
+
if (assoc_name, *assoc_method = column.split('__')).size > 1
|
77
|
+
# column is an association column
|
78
|
+
assoc_method = assoc_method.join('__') # in case we get something like country__continent__name
|
79
|
+
association = reflect_on_association(assoc_name.to_sym) || raise(NameError, "Association #{assoc_name} not known for class #{name}")
|
80
|
+
association.klass.options_for(assoc_method, query)
|
81
|
+
else
|
82
|
+
column = assoc_name
|
83
|
+
if self.column_names.include?(column)
|
84
|
+
# it's simply a column in the table
|
85
|
+
records = query.nil? ? find_by_sql("select distinct #{column} from #{table_name}") : find_by_sql("select distinct #{column} from #{table_name} where #{column} like '#{query}%'")
|
86
|
+
records.map{|r| r.send(column)}
|
87
|
+
else
|
88
|
+
# it's a "virtual" column - the least effective search
|
89
|
+
records = self.find(:all).map{|r| r.send(column)}.uniq
|
90
|
+
query.nil? ? records : records.select{|r| r.index(/^#{query}/)}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Extend ActiveRecord
|
102
|
+
ActiveRecord::Base.class_eval do
|
103
|
+
include Netzke::ActiveRecord::Basepack
|
104
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Netzke::ActiveRecord
|
2
|
+
# Provides extensions to those ActiveRecord-based models that provide data to the "data accessor" widgets,
|
3
|
+
# like GridPanel, FormPanel, etc
|
4
|
+
module DataAccessor
|
5
|
+
|
6
|
+
# Allow specify the netzke widget that requires this data. Virtual attributes may be using it to produce
|
7
|
+
# widget-dependent result.
|
8
|
+
def netzke_widget=(widget)
|
9
|
+
@netzke_widget = widget
|
10
|
+
end
|
11
|
+
|
12
|
+
def netzke_widget
|
13
|
+
@netzke_widget
|
14
|
+
end
|
15
|
+
|
16
|
+
# Transforms a record to array of values according to the passed columns.
|
17
|
+
def to_array(columns, widget = nil)
|
18
|
+
self.netzke_widget = widget
|
19
|
+
res = []
|
20
|
+
for c in columns
|
21
|
+
nc = c.is_a?(Symbol) ? {:name => c} : c
|
22
|
+
begin
|
23
|
+
res << send(nc[:name]) unless nc[:excluded]
|
24
|
+
rescue
|
25
|
+
# So that we don't crash at a badly configured column
|
26
|
+
res << "UNDEF"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
res
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
data/lib/netzke/basic_app.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
module Netzke
|
2
|
-
#
|
2
|
+
# == BasicApp
|
3
3
|
# Basis for a Ext.Viewport-based application
|
4
4
|
#
|
5
5
|
# Features:
|
6
6
|
# * dynamic loading of widgets
|
7
|
-
# * restoring of the last loaded widget (not working for now)
|
8
7
|
# * authentification support
|
9
8
|
# * browser history support (press the "Back"-button to go to the previously loaded widget)
|
10
9
|
# * FeedbackGhost-powered feedback
|
11
10
|
# * aggregation of widget's own menus
|
12
|
-
#
|
11
|
+
# * masquerade support
|
12
|
+
# * AJAX activity indicator
|
13
13
|
class BasicApp < Base
|
14
|
-
interface :app_get_widget # to dynamically load the widgets that are defined in initial_late_aggregatees
|
15
|
-
|
16
14
|
module ClassMethods
|
17
15
|
|
18
16
|
def js_base_class
|
@@ -22,161 +20,259 @@ module Netzke
|
|
22
20
|
# Global BasicApp configuration
|
23
21
|
def config
|
24
22
|
set_default_config({
|
25
|
-
:logout_url => "/logout" # logout url
|
23
|
+
:logout_url => "/logout" # default logout url
|
26
24
|
})
|
27
25
|
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
:xtype => 'toolbar',
|
40
|
-
:region => 'north',
|
41
|
-
:height => 25
|
42
|
-
}]
|
43
|
-
})
|
44
|
-
end
|
45
|
-
|
46
|
-
def js_after_constructor
|
47
|
-
<<-JS.l
|
48
|
-
// call appLoaded() once after the application is fully rendered
|
49
|
-
// this.on("resize", function(){alert('show');this.appLoaded();}, this, {single:true});
|
50
|
-
|
51
|
-
// Initialize menus (upcoming support for dynamically loaded menus)
|
52
|
-
this.menus = {};
|
53
|
-
|
54
|
-
Ext.History.on('change', this.processHistory, this);
|
55
|
-
|
56
|
-
// If we are given a token, load the corresponding widget, otherwise load the last loaded widget
|
57
|
-
var currentToken = Ext.History.getToken();
|
58
|
-
if (currentToken != "") {
|
59
|
-
this.processHistory(currentToken)
|
60
|
-
} else {
|
61
|
-
var lastLoaded = this.initialConfig.widgetToLoad; // passed from the server
|
62
|
-
if (lastLoaded) Ext.History.add(lastLoaded);
|
63
|
-
}
|
64
|
-
|
65
|
-
if (this.initialConfig.menu) {this.addMenu(this.initialConfig.menu, this);}
|
66
|
-
|
67
|
-
// add initial menus to the tool-bar
|
68
|
-
var toolbar = this.findById('main-toolbar');
|
69
|
-
Ext.each(#{js_initial_menus.to_js}, function(menu){
|
70
|
-
toolbar.add(menu);
|
71
|
-
});
|
72
|
-
JS
|
73
|
-
end
|
74
|
-
|
75
|
-
# Set the Logout button if Netzke::Base.user is set
|
76
|
-
def js_initial_menus
|
77
|
-
res = []
|
78
|
-
user = Netzke::Base.user
|
79
|
-
if !user.nil?
|
80
|
-
user_name = user.respond_to?(:name) ? user.name : user.login # try to display user's name, fallback to login
|
81
|
-
res << "->" <<
|
82
|
-
{
|
83
|
-
:text => "Logout #{user_name}",
|
84
|
-
:handler => <<-JS.l,
|
85
|
-
function(){
|
86
|
-
Ext.MessageBox.confirm('Confirm', 'Are you sure you want to logout?', function(btn){
|
87
|
-
if( btn == "yes" ) {
|
88
|
-
this.logout();
|
89
|
-
}
|
90
|
-
}.createDelegate(this));
|
91
|
-
}
|
92
|
-
JS
|
93
|
-
:scope => this
|
94
|
-
}
|
95
|
-
else
|
96
|
-
res << "->" <<
|
97
|
-
{
|
98
|
-
:text => "Login",
|
99
|
-
:handler => <<-JS.l,
|
100
|
-
function(){
|
101
|
-
window.location = "/login"
|
102
|
-
}
|
103
|
-
JS
|
104
|
-
:scope => this
|
105
|
-
}
|
27
|
+
def js_panels
|
28
|
+
# In status bar we want to show what we are masquerading as
|
29
|
+
if session[:masq_user]
|
30
|
+
user = User.find(session[:masq_user])
|
31
|
+
masq = %Q{user "#{user.login}"}
|
32
|
+
elsif session[:masq_role]
|
33
|
+
role = Role.find(session[:masq_role])
|
34
|
+
masq = %Q{role "#{role.name}"}
|
35
|
+
elsif session[:masq_world]
|
36
|
+
masq = %Q{World}
|
106
37
|
end
|
107
|
-
|
38
|
+
|
39
|
+
[{
|
40
|
+
:id => 'main-panel',
|
41
|
+
:region => 'center',
|
42
|
+
:layout => 'fit'
|
43
|
+
},{
|
44
|
+
:id => 'main-toolbar',
|
45
|
+
:xtype => 'toolbar',
|
46
|
+
:region => 'north',
|
47
|
+
:height => 25
|
48
|
+
# :items => ["-"]
|
49
|
+
},{
|
50
|
+
:id => 'main-statusbar',
|
51
|
+
:xtype => 'statusbar',
|
52
|
+
:region => 'south',
|
53
|
+
:statusAlign => 'right',
|
54
|
+
:busyText => 'Busy...',
|
55
|
+
:default_text => masq.nil? ? "Ready #{"(config mode)" if session[:config_mode]}" : "Masquerading as #{masq}",
|
56
|
+
:default_icon_cls => ""
|
57
|
+
}]
|
108
58
|
end
|
109
59
|
|
110
60
|
def js_extend_properties
|
111
|
-
|
61
|
+
{
|
62
|
+
:layout => 'border',
|
63
|
+
|
64
|
+
:panels => js_panels,
|
65
|
+
|
66
|
+
:init_component => <<-END_OF_JAVASCRIPT.l,
|
67
|
+
function(){
|
68
|
+
this.items = this.panels; // a bit weird, but working; can't assign it straight
|
69
|
+
|
70
|
+
Ext.netzke.cache.BasicApp.superclass.initComponent.call(this);
|
71
|
+
|
72
|
+
// If we are given a token, load the corresponding widget, otherwise load the last loaded widget
|
73
|
+
var currentToken = Ext.History.getToken();
|
74
|
+
if (currentToken != "") {
|
75
|
+
this.processHistory(currentToken)
|
76
|
+
} else {
|
77
|
+
var lastLoaded = this.initialConfig.widgetToLoad; // passed from the server
|
78
|
+
if (lastLoaded) Ext.History.add(lastLoaded);
|
79
|
+
}
|
112
80
|
|
113
|
-
|
81
|
+
Ext.History.on('change', this.processHistory, this);
|
82
|
+
|
83
|
+
// Hosted menus
|
84
|
+
this.menus = {};
|
85
|
+
|
86
|
+
// Setting the "busy" indicator for Ajax requests
|
87
|
+
Ext.Ajax.on('beforerequest', function(){this.findById('main-statusbar').showBusy()}, this);
|
88
|
+
Ext.Ajax.on('requestcomplete', function(){this.findById('main-statusbar').hideBusy()}, this);
|
89
|
+
Ext.Ajax.on('requestexception', function(){this.findById('main-statusbar').hideBusy()}, this);
|
90
|
+
}
|
91
|
+
END_OF_JAVASCRIPT
|
92
|
+
|
93
|
+
:host_menu => <<-END_OF_JAVASCRIPT.l,
|
114
94
|
function(menu, owner){
|
115
95
|
var toolbar = this.findById('main-toolbar');
|
116
96
|
if (!this.menus[owner.id]) this.menus[owner.id] = [];
|
117
97
|
Ext.each(menu, function(item) {
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
98
|
+
// var newMenu = new Ext.Toolbar.Button(item);
|
99
|
+
// var position = toolbar.items.getCount() - 2;
|
100
|
+
// position = position < 0 ? 0 : position;
|
101
|
+
// toolbar.insertButton(position, newMenu);
|
102
|
+
|
103
|
+
toolbar.add(item);
|
104
|
+
// this.menus[owner.id].push(newMenu); // TODO: remember the menus from this owner in some other way
|
123
105
|
}, this);
|
124
106
|
}
|
125
|
-
|
107
|
+
END_OF_JAVASCRIPT
|
126
108
|
|
127
|
-
:unhost_menu => <<-
|
109
|
+
:unhost_menu => <<-END_OF_JAVASCRIPT.l,
|
128
110
|
function(owner){
|
129
|
-
var toolbar = this.findById('main-toolbar');
|
130
|
-
if (this.menus[owner.id]) {
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
}
|
111
|
+
// var toolbar = this.findById('main-toolbar');
|
112
|
+
// if (this.menus[owner.id]) {
|
113
|
+
// Ext.each(this.menus[owner.id], function(menu){
|
114
|
+
// toolbar.items.remove(menu); // remove the item from the toolbar
|
115
|
+
// menu.destroy(); // ... and destroy it
|
116
|
+
// });
|
117
|
+
// }
|
136
118
|
}
|
137
|
-
|
119
|
+
END_OF_JAVASCRIPT
|
138
120
|
|
139
|
-
:logout => <<-
|
121
|
+
:logout => <<-END_OF_JAVASCRIPT.l,
|
140
122
|
function(){
|
141
123
|
window.location = "#{config[:logout_url]}"
|
142
124
|
}
|
143
|
-
|
125
|
+
END_OF_JAVASCRIPT
|
144
126
|
|
145
127
|
# Event handler for history change
|
146
|
-
:process_history => <<-
|
128
|
+
:process_history => <<-END_OF_JAVASCRIPT.l,
|
147
129
|
function(token){
|
148
130
|
if (token){
|
149
|
-
this.
|
131
|
+
this.loadAggregatee({id:token, container:'main-panel'});
|
150
132
|
} else {
|
151
|
-
this.findById('main-panel').loadWidget(null)
|
152
133
|
}
|
153
134
|
}
|
154
|
-
|
135
|
+
END_OF_JAVASCRIPT
|
136
|
+
|
137
|
+
:instantiate_aggregatee => <<-END_OF_JAVASCRIPT.l,
|
138
|
+
function(config){
|
139
|
+
this.findById('main-panel').instantiateChild(config);
|
140
|
+
}
|
141
|
+
END_OF_JAVASCRIPT
|
155
142
|
|
156
143
|
# Loads widget by name
|
157
|
-
:app_load_widget => <<-
|
144
|
+
:app_load_widget => <<-END_OF_JAVASCRIPT.l,
|
158
145
|
function(name){
|
159
|
-
Ext.History.add(name)
|
146
|
+
Ext.History.add(name);
|
160
147
|
}
|
161
|
-
|
148
|
+
END_OF_JAVASCRIPT
|
162
149
|
|
163
150
|
# Loads widget by action
|
164
|
-
:load_widget_by_action => <<-
|
151
|
+
:load_widget_by_action => <<-END_OF_JAVASCRIPT.l,
|
165
152
|
function(action){
|
166
|
-
this.appLoadWidget(action.widget || action.name)
|
153
|
+
this.appLoadWidget(action.widget || action.name);
|
167
154
|
}
|
168
|
-
|
169
|
-
|
155
|
+
END_OF_JAVASCRIPT
|
156
|
+
|
157
|
+
# Masquerade selector window
|
158
|
+
:show_masquerade_selector => <<-END_OF_JAVASCRIPT.l
|
159
|
+
function(){
|
160
|
+
var w = new Ext.Window({
|
161
|
+
title: 'Masquerade as',
|
162
|
+
modal: true,
|
163
|
+
width: Ext.lib.Dom.getViewWidth() * 0.6,
|
164
|
+
height: Ext.lib.Dom.getViewHeight() * 0.6,
|
165
|
+
layout: 'fit',
|
166
|
+
closeAction :'destroy',
|
167
|
+
buttons: [{
|
168
|
+
text: 'Select',
|
169
|
+
handler : function(){
|
170
|
+
if (role = w.getWidget().masquerade.role) {
|
171
|
+
Ext.Msg.confirm("Masquerading as a role", "Individual preferences for all users with this role will get overwritten as you make changes. Continue?", function(btn){
|
172
|
+
if (btn === 'yes') {
|
173
|
+
w.close();
|
174
|
+
}
|
175
|
+
});
|
176
|
+
} else {
|
177
|
+
w.close();
|
178
|
+
}
|
179
|
+
},
|
180
|
+
scope:this
|
181
|
+
},{
|
182
|
+
text:'As World',
|
183
|
+
handler:function(){
|
184
|
+
Ext.Msg.confirm("Masquerading as World", "Caution! All settings that you will modify will be ovewritten for all roles and all users. Are you sure you know what you're doing?", function(btn){
|
185
|
+
if (btn === "yes") {
|
186
|
+
this.masquerade = {world:true};
|
187
|
+
w.close();
|
188
|
+
}
|
189
|
+
}, this);
|
190
|
+
},
|
191
|
+
scope:this
|
192
|
+
},{
|
193
|
+
text:'No masquerading',
|
194
|
+
handler:function(){
|
195
|
+
this.masquerade = {};
|
196
|
+
w.close();
|
197
|
+
},
|
198
|
+
scope:this
|
199
|
+
},{
|
200
|
+
text:'Cansel',
|
201
|
+
handler:function(){
|
202
|
+
w.hide();
|
203
|
+
},
|
204
|
+
scope:this
|
205
|
+
}],
|
206
|
+
listeners : {close: {fn: function(){
|
207
|
+
this.masqueradeAs(this.masquerade || w.getWidget().masquerade || {});
|
208
|
+
}, scope: this}}
|
209
|
+
});
|
210
|
+
|
211
|
+
w.show(null, function(){
|
212
|
+
this.loadAggregatee({id:"masqueradeSelector", container:w.id})
|
213
|
+
}, this);
|
214
|
+
|
215
|
+
}
|
216
|
+
END_OF_JAVASCRIPT
|
217
|
+
}
|
170
218
|
end
|
171
219
|
end
|
172
220
|
|
173
221
|
extend ClassMethods
|
222
|
+
|
223
|
+
# Set the Logout button if Netzke::Base.user is set
|
224
|
+
def menu
|
225
|
+
res = []
|
226
|
+
user = Netzke::Base.user
|
227
|
+
if !user.nil?
|
228
|
+
user_name = user.respond_to?(:name) ? user.name : user.login # try to display user's name, fallback to login
|
229
|
+
res << "->" <<
|
230
|
+
{
|
231
|
+
:text => "#{user_name}",
|
232
|
+
:menu => user_menu
|
233
|
+
}
|
234
|
+
else
|
235
|
+
res << "->" <<
|
236
|
+
{
|
237
|
+
:text => "Login",
|
238
|
+
:handler => <<-END_OF_JAVASCRIPT.l,
|
239
|
+
function(){
|
240
|
+
window.location = "/login"
|
241
|
+
}
|
242
|
+
END_OF_JAVASCRIPT
|
243
|
+
:scope => this
|
244
|
+
}
|
245
|
+
end
|
246
|
+
res
|
247
|
+
end
|
248
|
+
|
249
|
+
def user_menu
|
250
|
+
['logout']
|
251
|
+
end
|
252
|
+
|
253
|
+
def initialize(*args)
|
254
|
+
super
|
255
|
+
|
256
|
+
if session[:netzke_just_logged_in] || session[:netzke_just_logged_out]
|
257
|
+
session[:config_mode] = false
|
258
|
+
session[:masq_world] = session[:masq_user] = session[:masq_roles] = nil
|
259
|
+
end
|
260
|
+
|
261
|
+
strong_children_config.deep_merge!({:ext_config => {:mode => :config}}) if session[:config_mode]
|
262
|
+
end
|
174
263
|
|
175
|
-
#
|
176
|
-
|
177
|
-
|
264
|
+
#
|
265
|
+
# Available actions
|
266
|
+
#
|
267
|
+
def actions
|
268
|
+
{
|
269
|
+
:masquerade_selector => {:text => "Masquerade as ...", :fn => "showMasqueradeSelector"},
|
270
|
+
:toggle_config_mode => {:text => "#{session[:config_mode] ? "Leave" : "Enter"} config mode", :fn => "toggleConfigMode"},
|
271
|
+
:logout => {:text => "Log out", :fn => "logout"}
|
272
|
+
}
|
178
273
|
end
|
179
274
|
|
275
|
+
|
180
276
|
# Html required for Ext.History to work
|
181
277
|
def js_widget_html
|
182
278
|
super << %Q{
|
@@ -194,18 +290,31 @@ module Netzke
|
|
194
290
|
|
195
291
|
# Besides instantiating ourselves, also instantiate the FeedbackGhost
|
196
292
|
def js_widget_instance
|
197
|
-
|
293
|
+
<<-END_OF_JAVASCRIPT << super
|
198
294
|
new Ext.netzke.cache['FeedbackGhost']({id:'feedback_ghost'})
|
199
295
|
// Initialize history (can't say why it's not working well inside the appLoaded handler)
|
200
296
|
Ext.History.init();
|
201
|
-
|
297
|
+
END_OF_JAVASCRIPT
|
202
298
|
end
|
299
|
+
|
300
|
+
#
|
301
|
+
# Interface section
|
302
|
+
#
|
203
303
|
|
204
|
-
|
205
|
-
def
|
206
|
-
|
207
|
-
|
208
|
-
|
304
|
+
api :toggle_config_mode
|
305
|
+
def toggle_config_mode(params)
|
306
|
+
session = Netzke::Base.session
|
307
|
+
session[:config_mode] = !session[:config_mode]
|
308
|
+
{:js => "window.location.reload();"}
|
309
|
+
end
|
310
|
+
|
311
|
+
api :masquerade_as
|
312
|
+
def masquerade_as(params)
|
313
|
+
session = Netzke::Base.session
|
314
|
+
session[:masq_world] = params[:world]
|
315
|
+
session[:masq_role] = params[:role]
|
316
|
+
session[:masq_user] = params[:user]
|
317
|
+
{:js => "window.location.reload()"}
|
209
318
|
end
|
210
319
|
|
211
320
|
end
|