netzke-core 0.12.3 → 1.0.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +65 -607
- data/Gemfile +1 -1
- data/LICENSE +2 -6
- data/README.md +77 -145
- data/javascripts/base.js +582 -96
- data/javascripts/core.js +62 -0
- data/javascripts/notifications.js +43 -0
- data/javascripts/remoting_provider.js +29 -0
- data/javascripts/routing.js +63 -0
- data/lib/netzke/base.rb +16 -83
- data/lib/netzke/core/action_config.rb +1 -5
- data/lib/netzke/core/actions.rb +59 -21
- data/lib/netzke/core/{client_class.rb → client_class_config.rb} +81 -73
- data/lib/netzke/core/client_code.rb +157 -0
- data/lib/netzke/core/component_config.rb +2 -2
- data/lib/netzke/core/composition.rb +85 -65
- data/lib/netzke/core/configuration.rb +26 -14
- data/lib/netzke/core/core_i18n.rb +17 -0
- data/lib/netzke/core/css_config.rb +6 -6
- data/lib/netzke/core/dynamic_assets.rb +17 -24
- data/lib/netzke/core/embedding.rb +2 -2
- data/lib/netzke/core/endpoint_response.rb +8 -2
- data/lib/netzke/core/inheritance.rb +33 -0
- data/lib/netzke/core/plugins.rb +1 -4
- data/lib/netzke/core/railz/action_view_ext.rb +1 -1
- data/lib/netzke/core/railz/controller_extensions.rb +21 -15
- data/lib/netzke/core/services.rb +61 -48
- data/lib/netzke/core/session.rb +0 -2
- data/lib/netzke/core/state.rb +11 -9
- data/lib/netzke/core/stylesheets.rb +3 -3
- data/lib/netzke/core/version.rb +1 -1
- data/lib/netzke/core.rb +3 -3
- data/lib/netzke/plugin.rb +2 -6
- data/stylesheets/core.css +2 -2
- metadata +11 -10
- data/TODO.md +0 -9
- data/javascripts/ext.js +0 -518
- data/lib/netzke/core/config_to_dsl_delegator.rb +0 -62
- data/lib/netzke/core/dsl_support.rb +0 -70
- data/lib/netzke/core/html.rb +0 -29
- data/lib/netzke/core/javascript.rb +0 -123
data/javascripts/core.js
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
/*
|
2
|
+
* This file gets loaded along with the rest of Ext library at the initial load
|
3
|
+
* At this time the following constants have been set by Rails:
|
4
|
+
*
|
5
|
+
* * Netzke.RelativeUrlRoot - set to ActionController::Base.config.relative_url_root
|
6
|
+
* * Netzke.RelativeExtUrl - URL to ext files
|
7
|
+
* * Netzke.ControllerUrl - NetzkeController URL
|
8
|
+
*/
|
9
|
+
|
10
|
+
Ext.ns('Ext.netzke'); // namespace for extensions that depend on Ext JS
|
11
|
+
Ext.ns('Netzke.page'); // namespace for all component instances on the page
|
12
|
+
Ext.ns('Netzke.classes'); // namespace for component classes
|
13
|
+
|
14
|
+
Netzke.warning = function(msg){
|
15
|
+
if (typeof console != 'undefined') {
|
16
|
+
console.info("Netzke: " + msg);
|
17
|
+
}
|
18
|
+
};
|
19
|
+
|
20
|
+
Netzke.deprecationWarning = Netzke.warning;
|
21
|
+
|
22
|
+
Netzke.exception = function(msg) {
|
23
|
+
throw("Netzke: " + msg);
|
24
|
+
};
|
25
|
+
|
26
|
+
// Check Ext JS version: both major and minor versions must be the same
|
27
|
+
(function(){
|
28
|
+
var requiredVersionMajor = 5,
|
29
|
+
requiredVersionMinor = 1,
|
30
|
+
extVersion = Ext.getVersion('extjs'),
|
31
|
+
currentVersionMajor = extVersion.getMajor(),
|
32
|
+
currentVersionMinor = extVersion.getMinor(),
|
33
|
+
requiredString = "" + requiredVersionMajor + "." + requiredVersionMinor + ".x";
|
34
|
+
|
35
|
+
if (requiredVersionMajor != currentVersionMajor || requiredVersionMinor != currentVersionMinor) {
|
36
|
+
Netzke.warning("Ext JS " + requiredString + " required (you have " + extVersion.toString() + ").");
|
37
|
+
}
|
38
|
+
})();
|
39
|
+
|
40
|
+
// Netzke global event emitter
|
41
|
+
Ext.define('Netzke.GlobalEvents', {
|
42
|
+
extend: 'Ext.mixin.Observable',
|
43
|
+
singleton: true
|
44
|
+
});
|
45
|
+
|
46
|
+
// xtypes of cached Netzke classes
|
47
|
+
Netzke.cache = [];
|
48
|
+
|
49
|
+
// Because of Netzke's double-underscore notation, Ext.TabPanel should have a different id-delimiter (yes, this must be in netzke-core)
|
50
|
+
Ext.TabPanel.prototype.idDelimiter = "___";
|
51
|
+
|
52
|
+
// Enable quick tips
|
53
|
+
Ext.QuickTips.init();
|
54
|
+
|
55
|
+
// Used in testing
|
56
|
+
if( Netzke._pendingRequests == undefined ){
|
57
|
+
Netzke._pendingRequests=0;
|
58
|
+
Ext.Ajax.on('beforerequest', function(conn, opt) { Netzke._pendingRequests += 1; });
|
59
|
+
Ext.Ajax.on('requestcomplete', function(conn, opt) { Netzke._pendingRequests -= 1; });
|
60
|
+
Ext.Ajax.on('requestexception', function(conn, opt) { Netzke._pendingRequests -= 1; });
|
61
|
+
Netzke.ajaxIsLoading = function() { return Netzke._pendingRequests > 0; };
|
62
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
/**
|
2
|
+
* Class creating simple notifications. Borrowed from http://dev.sencha.com/extjs/5.1.0/examples/shared/examples.js
|
3
|
+
* @class Netzke.Notifier
|
4
|
+
*/
|
5
|
+
Ext.define('Netzke.Notifier', function(){
|
6
|
+
var msgCt;
|
7
|
+
|
8
|
+
function createBox(t, s){
|
9
|
+
return t ?
|
10
|
+
'<div class="msg ' + Ext.baseCSSPrefix + 'border-box"><h3>' + t + '</h3><p>' + s + '</p></div>'
|
11
|
+
:
|
12
|
+
'<div class="msg ' + Ext.baseCSSPrefix + 'border-box"><p>' + s + '</p></div>';
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
return {
|
17
|
+
/**
|
18
|
+
* Shows notification on the screen.
|
19
|
+
* @method msg
|
20
|
+
* @param {String} msg Notification body HTML
|
21
|
+
* @param {Object} options May contain the following keys:
|
22
|
+
*
|
23
|
+
* * **title** - title of notification
|
24
|
+
* * **delay** (ms) - time notification should stay on the screen
|
25
|
+
*/
|
26
|
+
msg: function(msg, options){
|
27
|
+
if (options == undefined) options = {};
|
28
|
+
|
29
|
+
if (Ext.isArray(msg)) {
|
30
|
+
msg = msg.join("<br>")
|
31
|
+
}
|
32
|
+
|
33
|
+
if (msgCt) {
|
34
|
+
document.body.appendChild(msgCt.dom);
|
35
|
+
} else {
|
36
|
+
msgCt = Ext.DomHelper.append(document.body, {id:'msg-div'}, true);
|
37
|
+
}
|
38
|
+
var m = Ext.DomHelper.append(msgCt, createBox(options.title, msg), true);
|
39
|
+
m.hide();
|
40
|
+
m.slideIn('t').ghost("t", { delay: options.delay || Netzke.Core.NotificationDelay, remove: true});
|
41
|
+
}
|
42
|
+
};
|
43
|
+
});
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Ext.define('Netzke.NetzkeRemotingProvider', {
|
2
|
+
|
3
|
+
extend: 'Ext.direct.RemotingProvider',
|
4
|
+
url: Netzke.ControllerUrl + "direct/", // url to connect to the Ext.Direct server-side router.
|
5
|
+
namespace: "Netzke.remotingMethods", // will have a key per Netzke component, each mapped to a hash with a RemotingMethod per endpoint
|
6
|
+
maxRetries: Netzke.Core.directMaxRetries,
|
7
|
+
enableBuffer: true, // buffer/batch requests within 10ms timeframe
|
8
|
+
timeout: 30000, // 30s timeout per request
|
9
|
+
|
10
|
+
getPayload: function(t){
|
11
|
+
return {
|
12
|
+
path: t.action,
|
13
|
+
endpoint: t.method,
|
14
|
+
data: t.data[0],
|
15
|
+
tid: t.id,
|
16
|
+
type: 'rpc'
|
17
|
+
}
|
18
|
+
},
|
19
|
+
|
20
|
+
// Adds remoting method to component
|
21
|
+
addRemotingMethodToComponent: function(componentConfig, methodName) {
|
22
|
+
var cls = this.namespace[componentConfig.id] || (this.namespace[componentConfig.id] = {});
|
23
|
+
var method = Ext.create('Ext.direct.RemotingMethod', {name: methodName, len: 1});
|
24
|
+
cls[methodName] = this.createHandler(componentConfig.path, method);
|
25
|
+
}
|
26
|
+
});
|
27
|
+
|
28
|
+
Netzke.directProvider = Ext.create(Netzke.NetzkeRemotingProvider);
|
29
|
+
Ext.Direct.addProvider(Netzke.directProvider);
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/**
|
2
|
+
* Routing override for Netzke.Base.
|
3
|
+
* @class Netzke.Core.Routing
|
4
|
+
*/
|
5
|
+
Ext.define('Netzke.Core.Routing', {
|
6
|
+
override: 'Netzke.Base',
|
7
|
+
|
8
|
+
netzkeAfterInitComponent: function(){
|
9
|
+
if (this.netzkeRoutes) {
|
10
|
+
var routes = this.netzkeGetRoutes();
|
11
|
+
this.netzkeRouter = Ext.create('Ext.app.Controller', { routes: this.netzkeGetRoutes() });
|
12
|
+
this.on('beforedestroy', this.netzkeCleanRoutes, this);
|
13
|
+
|
14
|
+
this.on('render', function(){
|
15
|
+
this.netzkeTriggerInitialRoute();
|
16
|
+
});
|
17
|
+
}
|
18
|
+
|
19
|
+
this.callParent();
|
20
|
+
},
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Navigate to new hash route.
|
24
|
+
* @method netzkeNavigateTo
|
25
|
+
* @param route {String} Route
|
26
|
+
* @param {Object} [options] Options:
|
27
|
+
* * **append** {Boolean} append to the current route
|
28
|
+
*
|
29
|
+
* @example
|
30
|
+
*
|
31
|
+
* this.netzkeNavigateTo('user/1', {append: true})
|
32
|
+
*/
|
33
|
+
netzkeNavigateTo: function(route, options){
|
34
|
+
options = options || {};
|
35
|
+
var newRoute = route;
|
36
|
+
if (options.append) {
|
37
|
+
newRoute = Ext.util.History.getToken() + "/" + newRoute;
|
38
|
+
}
|
39
|
+
Ext.util.History.add(newRoute);
|
40
|
+
},
|
41
|
+
|
42
|
+
// private
|
43
|
+
|
44
|
+
netzkeCleanRoutes: function(){
|
45
|
+
this.netzkeRouter.destroy();
|
46
|
+
},
|
47
|
+
|
48
|
+
netzkeTriggerInitialRoute: function(){
|
49
|
+
var initToken = Ext.util.History.getToken();
|
50
|
+
if (initToken) this.netzkeRouter.redirectTo(initToken, true);
|
51
|
+
},
|
52
|
+
|
53
|
+
netzkeGetRoutes: function(){
|
54
|
+
var out = {};
|
55
|
+
for (var route in this.netzkeRoutes) {
|
56
|
+
var handlerName = this.netzkeRoutes[route],
|
57
|
+
handler = this[handlerName];
|
58
|
+
if (!handler) Netzke.exception("Route handler " + handlerName + " is not defined");
|
59
|
+
out[route] = handler.bind(this);
|
60
|
+
}
|
61
|
+
return out;
|
62
|
+
}
|
63
|
+
});
|
data/lib/netzke/base.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext'
|
2
2
|
require 'netzke/core/ruby_ext'
|
3
|
-
require 'netzke/core/
|
4
|
-
require 'netzke/core/javascript'
|
3
|
+
require 'netzke/core/client_code'
|
5
4
|
require 'netzke/core/stylesheets'
|
6
5
|
require 'netzke/core/services'
|
7
6
|
require 'netzke/core/composition'
|
@@ -11,17 +10,20 @@ require 'netzke/core/state'
|
|
11
10
|
require 'netzke/core/embedding'
|
12
11
|
require 'netzke/core/actions'
|
13
12
|
require 'netzke/core/session'
|
14
|
-
require 'netzke/core/
|
13
|
+
require 'netzke/core/core_i18n'
|
14
|
+
require 'netzke/core/inheritance'
|
15
15
|
|
16
16
|
module Netzke
|
17
17
|
# The base class for every Netzke component. Its main responsibilities include:
|
18
|
-
# *
|
18
|
+
# * Client class generation and inheritance (using Ext JS class system) which reflects the Ruby class inheritance (see {Netzke::Core::ClientCode})
|
19
19
|
# * Nesting and dynamic loading of child components (see {Netzke::Core::Composition})
|
20
20
|
# * Ruby-side action declaration (see {Netzke::Actions})
|
21
21
|
# * I18n
|
22
22
|
# * Client-server communication (see {Netzke::Core::Services})
|
23
23
|
# * Session-based persistence (see {Netzke::Core::State})
|
24
24
|
#
|
25
|
+
# Client-side methods are documented [here](http://api.netzke.org/client/classes/Netzke.Base.html).
|
26
|
+
#
|
25
27
|
# == Referring to JavaScript configuration methods from Ruby
|
26
28
|
#
|
27
29
|
# Netzke allows use Ruby symbols for referring to pre-defined pieces of configuration. Let's say for example, that a toolbar needs to nest a control more complex than a button (say, a date field), and a component should still make it possible to make it's presence and position in the toolbar configurable. We can implement it like this:
|
@@ -33,7 +35,7 @@ module Netzke
|
|
33
35
|
# c.tbar = [:do_something, :date_selector]
|
34
36
|
# end
|
35
37
|
#
|
36
|
-
# While :do_something here is referring to a usual Netzke action, :date_selector is not declared in actions. If our JavaScript
|
38
|
+
# While :do_something here is referring to a usual Netzke action, :date_selector is not declared in actions. If our JavaScript include file contains a method called `dateSelectorConfig`, it will be executed at the moment of configuring `tbar` at client side, and it's result, a config object, will substitute `date_selector`:
|
37
39
|
#
|
38
40
|
# {
|
39
41
|
# dateSelectorConfig: function(config){
|
@@ -45,73 +47,23 @@ module Netzke
|
|
45
47
|
#
|
46
48
|
# This doesn't necessarily have to be used in toolbars, but also in other places in config (i.e. layouts).
|
47
49
|
class Base
|
48
|
-
include Core::DslSupport
|
49
50
|
include Core::Session
|
50
51
|
include Core::State
|
51
52
|
include Core::Configuration
|
52
|
-
include Core::
|
53
|
+
include Core::ClientCode
|
53
54
|
include Core::Services
|
54
55
|
include Core::Composition
|
55
56
|
include Core::Plugins
|
56
57
|
include Core::Stylesheets
|
57
58
|
include Core::Embedding
|
58
59
|
include Core::Actions
|
59
|
-
include Core::
|
60
|
-
|
61
|
-
# TODO: get rid of it
|
62
|
-
class_attribute :default_instance_config
|
63
|
-
self.default_instance_config = {}
|
64
|
-
|
65
|
-
# set during initializations
|
66
|
-
mattr_accessor :session
|
67
|
-
mattr_accessor :controller
|
68
|
-
mattr_accessor :logger
|
69
|
-
|
70
|
-
# Parent component
|
71
|
-
attr_reader :parent
|
72
|
-
|
73
|
-
# Name that the parent can reference us by
|
74
|
-
attr_reader :name
|
75
|
-
|
76
|
-
# Global id in the component tree, following the double-underscore notation, e.g. +books__config_panel__form+
|
77
|
-
attr_reader :js_id
|
78
|
-
|
79
|
-
# JS id in the context of the parent
|
80
|
-
attr_reader :item_id
|
81
|
-
|
82
|
-
# Component's path in the component tree
|
83
|
-
attr_reader :path
|
84
|
-
|
85
|
-
class << self
|
86
|
-
# Instance of component by config
|
87
|
-
def instance_by_config(config)
|
88
|
-
klass = config[:klass] || config[:class_name].constantize
|
89
|
-
klass.new(config)
|
90
|
-
end
|
91
|
-
|
92
|
-
# The ID used to locate this component's block in locale files
|
93
|
-
def i18n_id
|
94
|
-
name.split("::").map{|c| c.underscore}.join(".")
|
95
|
-
end
|
60
|
+
include Core::CoreI18n
|
61
|
+
include Core::Inheritance
|
96
62
|
|
97
|
-
|
98
|
-
|
99
|
-
# Netzke::Basepack::GridPanel.setup do |c|
|
100
|
-
# c.rows_reordering_available = false
|
101
|
-
# end
|
102
|
-
def self.setup
|
103
|
-
yield self
|
104
|
-
end
|
63
|
+
# These are set during initialization
|
64
|
+
mattr_accessor :session, :controller, :logger
|
105
65
|
|
106
|
-
|
107
|
-
def netzke_ancestors
|
108
|
-
if self == Netzke::Base
|
109
|
-
[]
|
110
|
-
else
|
111
|
-
superclass.netzke_ancestors + [self]
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
66
|
+
attr_reader :parent, :name, :item_id, :path
|
115
67
|
|
116
68
|
# Instantiates a component instance. A parent can optionally be provided.
|
117
69
|
def initialize(conf = {}, parent = nil)
|
@@ -130,37 +82,18 @@ module Netzke
|
|
130
82
|
# Full JS id will be built using these along the +@path+
|
131
83
|
@item_id = conf[:item_id] || @name
|
132
84
|
|
133
|
-
# JS full ID. Similar to +path+, but composed of item_id's. Differs from @path when multiple instances are being loaded.
|
134
|
-
@js_id = conf[:js_id]
|
135
|
-
@js_id ||= parent.nil? ? @item_id : [parent.js_id, @item_id].join("__")
|
136
|
-
|
137
|
-
# TODO: get rid of this in 0.9
|
138
|
-
@flash = []
|
139
|
-
|
140
85
|
# Make +client_config+ accessible in +configure+ before calling +super+
|
141
86
|
config.client_config = (conf.delete(:client_config) || {}).symbolize_keys
|
142
87
|
|
143
88
|
# Build complete component configuration
|
144
89
|
configure(config)
|
145
90
|
|
146
|
-
|
147
|
-
|
148
|
-
# Check whether the config is valid
|
91
|
+
# Check whether the config is valid (as specified in a custom override)
|
149
92
|
validate_config(config)
|
150
|
-
end
|
151
|
-
|
152
|
-
def i18n_id
|
153
|
-
self.class.i18n_id
|
154
|
-
end
|
155
93
|
|
156
|
-
|
94
|
+
normalize_config
|
157
95
|
|
158
|
-
|
159
|
-
def flash(flash_hash)
|
160
|
-
level = flash_hash.keys.first
|
161
|
-
raise "Unknown message level for flash" unless %(notice warning error).include?(level.to_s)
|
162
|
-
@flash << {:level => level, :msg => flash_hash[level]}
|
96
|
+
config.deep_freeze
|
163
97
|
end
|
164
|
-
|
165
98
|
end
|
166
99
|
end
|
@@ -22,12 +22,8 @@ module Netzke::Core
|
|
22
22
|
self.icon = @icon.to_sym if @icon.present?
|
23
23
|
end
|
24
24
|
|
25
|
-
def icon=(path)
|
26
|
-
self[:icon] = path.is_a?(Symbol) ? Netzke::Base.uri_to_icon(path) : path
|
27
|
-
end
|
28
|
-
|
29
|
-
# later
|
30
25
|
def set_defaults!
|
26
|
+
self[:icon] = icon.is_a?(Symbol) ? Netzke::Base.uri_to_icon(icon) : icon
|
31
27
|
end
|
32
28
|
|
33
29
|
private
|
data/lib/netzke/core/actions.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Netzke::Core
|
2
|
-
# Netzke components
|
2
|
+
# Netzke components provide for convenient configuration of Ext JS actions from the Ruby class.
|
3
3
|
#
|
4
4
|
# == Defining actions
|
5
5
|
#
|
@@ -9,21 +9,26 @@ module Netzke::Core
|
|
9
9
|
# c.text = "Destroy!"
|
10
10
|
# c.tooltip = "Destroying it all"
|
11
11
|
# c.icon = :delete
|
12
|
-
# c.handler = :destroy_something # destroySomething will be called on
|
12
|
+
# c.handler = :destroy_something # `this.destroySomething` will be called on client side
|
13
13
|
# end
|
14
14
|
#
|
15
15
|
# All config settings for an action are optional. When omitted, the locale files will be consulted first (see "I18n of actions"), falling back to the defaults.
|
16
16
|
#
|
17
|
-
# [
|
18
|
-
# The text of the action (defaults to
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# [
|
17
|
+
# [text]
|
18
|
+
# The text of the action (defaults to localized action text, see on I18n below)
|
19
|
+
#
|
20
|
+
# [icon]
|
21
|
+
# Can be set to either a String (which will be interpreted as a full URI to the icon file), or as a Symbol, which will be expanded to +Netzke::Core.icons_uri+ + "/(icon).png". Defaults to localized action icon (see on I18n below) or nil (no icon)
|
22
|
+
#
|
23
|
+
# [tooltip]
|
24
|
+
# The tooltip of the action (defaults to localized action tooltip, see on I18n below)
|
25
|
+
#
|
26
|
+
# [disabled]
|
24
27
|
# When set to +true+, renders this action as disabled
|
25
|
-
#
|
26
|
-
#
|
28
|
+
#
|
29
|
+
# [handler]
|
30
|
+
# A symbol that represents the JavaScript public method (snake-cased), which will be called in the scope of the component instance. Defaults to +netzke_on_{action_name}+, which on JavaScript side will result in a call to +netzkeOn{ActionName}+
|
31
|
+
#
|
27
32
|
# [+excluded+]
|
28
33
|
# When set to true, gets the action excluded from menus and toolbars
|
29
34
|
#
|
@@ -95,24 +100,53 @@ module Netzke::Core
|
|
95
100
|
#
|
96
101
|
# == Interfering with action events in client class
|
97
102
|
#
|
98
|
-
# For each action Netzke creates an event on the level of the parent component following the convention
|
103
|
+
# For each action Netzke creates an event on the level of the parent component following the convention `<action_name>click`. The handler receives the component itself as a parameter. If the handler returns +false+, the action event is not further propagated.
|
104
|
+
#
|
105
|
+
# == Preventing name clashing with child components
|
106
|
+
#
|
107
|
+
# If a component has an action and a child component defined with the same name, referring to them by symbols in the
|
108
|
+
# configuration will result in a name clash. See {Core::Composition} on how to address that.
|
99
109
|
module Actions
|
100
110
|
extend ActiveSupport::Concern
|
101
111
|
|
102
112
|
included do
|
103
|
-
|
104
|
-
|
113
|
+
class_attribute :_declared_actions
|
114
|
+
self._declared_actions = []
|
105
115
|
end
|
106
116
|
|
107
117
|
module ClassMethods
|
108
|
-
#
|
118
|
+
# Declares an action
|
119
|
+
def action(*args, &block)
|
120
|
+
args.each{|name| action(name)} if args.length > 1
|
121
|
+
|
122
|
+
name = args.first
|
123
|
+
|
124
|
+
define_method :"#{name}_action", &(block || ->(c){c})
|
125
|
+
# NOTE: "<<" won't work here as this will mutate the array shared between classes
|
126
|
+
self._declared_actions += [name]
|
127
|
+
end
|
128
|
+
|
109
129
|
# @return [String|nil] full URI to an icon file by its name (provided we have a controller)
|
130
|
+
# NOTE: must stay public, used from ActionConfig
|
110
131
|
def uri_to_icon(icon)
|
111
132
|
Netzke::Core.with_icons ? [(controller && controller.config.relative_url_root), Netzke::Core.icons_uri, '/', icon.to_s, ".png"].join : nil
|
112
133
|
end
|
113
134
|
end
|
114
135
|
|
115
|
-
def
|
136
|
+
def actions
|
137
|
+
return @actions if @actions
|
138
|
+
|
139
|
+
@actions = {}.tap do |res|
|
140
|
+
self.class._declared_actions.each do |name|
|
141
|
+
cfg = Netzke::Core::ActionConfig.new(name, self)
|
142
|
+
send("#{name}_action", cfg)
|
143
|
+
cfg.set_defaults!
|
144
|
+
res[name.to_sym] = cfg.excluded ? {excluded: true} : cfg
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def configure_client(c)
|
116
150
|
super
|
117
151
|
c.actions = actions
|
118
152
|
end
|
@@ -125,19 +159,23 @@ module Netzke::Core
|
|
125
159
|
|
126
160
|
def detect_and_normalize_action(item)
|
127
161
|
item = {action: item} if item.is_a?(Symbol) && actions[item]
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
if
|
162
|
+
|
163
|
+
if action_name = action_name_if_action(item)
|
164
|
+
action_config = actions[action_name]
|
165
|
+
if action_config[:excluded]
|
132
166
|
{excluded: true}
|
133
167
|
else
|
134
|
-
|
168
|
+
{action: action_name.to_s.camelize(:lower)}
|
135
169
|
end
|
136
170
|
else
|
137
171
|
item
|
138
172
|
end
|
139
173
|
end
|
140
174
|
|
175
|
+
def action_name_if_action(item)
|
176
|
+
item.is_a?(Hash) && item[:action]
|
177
|
+
end
|
178
|
+
|
141
179
|
def uri_to_icon(icon)
|
142
180
|
self.class.uri_to_icon(icon)
|
143
181
|
end
|