netzke-core 0.12.3 → 1.0.0.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.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
|