netzke-basepack 0.4.2 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|