netzke-basepack 0.6.4 → 0.6.5
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.rdoc +10 -0
- data/README.rdoc +1 -1
- data/Rakefile +1 -1
- data/javascripts/basepack.js +4 -108
- data/javascripts/feedback_ghost.js +34 -0
- data/lib/netzke/basepack.rb +1 -0
- data/lib/netzke/basepack/form_panel.rb +7 -6
- data/lib/netzke/basepack/form_panel/fields.rb +6 -14
- data/lib/netzke/basepack/form_panel/javascripts/form_panel.js +53 -27
- data/lib/netzke/basepack/form_panel/javascripts/misc.js +4 -0
- data/lib/netzke/basepack/form_panel/javascripts/readonly_mode.js +4 -21
- data/lib/netzke/basepack/form_panel/services.rb +10 -3
- data/lib/netzke/basepack/grid_panel.rb +40 -26
- data/lib/netzke/basepack/grid_panel/columns.rb +25 -0
- data/lib/netzke/basepack/grid_panel/javascripts/grid_panel.js +4 -2
- data/lib/netzke/basepack/grid_panel/services.rb +10 -33
- data/lib/netzke/basepack/search_window.rb +2 -2
- data/lib/netzke/basepack/version.rb +1 -1
- data/netzke-basepack.gemspec +44 -145
- data/test/rails_app/Gemfile +3 -5
- data/test/rails_app/Gemfile.lock +78 -84
- data/test/rails_app/app/components/book_form.rb +12 -0
- data/test/rails_app/app/components/book_grid_with_scoped_authors.rb +8 -0
- data/test/rails_app/app/components/book_paging_form_panel.rb +3 -2
- data/test/rails_app/app/components/form_without_model.rb +2 -1
- data/test/rails_app/app/views/components/loadable_window.html.erb +9 -0
- data/test/rails_app/app/views/layouts/application.html.erb +1 -1
- data/test/rails_app/config/cucumber.yml +8 -0
- data/test/rails_app/config/{database.yml → database.yml.sample} +4 -1
- data/test/rails_app/config/locales/es.yml +4 -1
- data/{features → test/rails_app/features}/accordion_panel.feature +1 -4
- data/{features → test/rails_app/features}/components_in_view.feature +0 -0
- data/{features → test/rails_app/features}/form_panel.feature +18 -13
- data/{features → test/rails_app/features}/grid_panel.feature +0 -0
- data/test/rails_app/features/i18n.feature +18 -0
- data/{features → test/rails_app/features}/nested_attributes.feature +0 -0
- data/{features → test/rails_app/features}/paging_form_panel.feature +13 -1
- data/{features → test/rails_app/features}/search_in_grid.feature +0 -0
- data/{features → test/rails_app/features}/simple_app.feature +0 -0
- data/{features → test/rails_app/features}/simple_panel.feature +1 -5
- data/{features → test/rails_app/features}/step_definitions/accordion_steps.rb +0 -0
- data/{features → test/rails_app/features}/step_definitions/form_panel_steps.rb +1 -1
- data/{features → test/rails_app/features}/step_definitions/generic_steps.rb +0 -0
- data/{features → test/rails_app/features}/step_definitions/grid_panel_steps.rb +0 -0
- data/{features → test/rails_app/features}/step_definitions/pickle_steps.rb +0 -0
- data/{features → test/rails_app/features}/step_definitions/web_steps.rb +0 -0
- data/{features → test/rails_app/features}/support/env.rb +14 -13
- data/test/rails_app/features/support/paths.rb +24 -6
- data/{features → test/rails_app/features}/support/pickle.rb +0 -0
- data/test/rails_app/features/support/selectors.rb +39 -0
- data/{features → test/rails_app/features}/tab_panel.feature +1 -4
- data/{features → test/rails_app/features}/validations_in_grid.feature +0 -0
- data/{features → test/rails_app/features}/virtual_attributes.feature +0 -0
- data/{features → test/rails_app/features}/window.feature +0 -0
- data/test/rails_app/lib/tasks/cucumber.rake +71 -0
- data/test/rails_app/script/cucumber +10 -0
- data/{spec → test/rails_app/spec}/active_record/attributes_spec.rb +0 -0
- data/{spec → test/rails_app/spec}/active_record/relation_extensions_spec.rb +0 -0
- data/{spec → test/rails_app/spec}/components/form_panel_spec.rb +0 -0
- data/{spec → test/rails_app/spec}/components/grid_panel_spec.rb +0 -0
- data/{spec → test/rails_app/spec}/factories.rb +0 -0
- data/{spec → test/rails_app/spec}/spec_helper.rb +1 -6
- metadata +43 -141
- data/autotest/discover.rb +0 -3
- data/config/database.yml +0 -2
- data/features/i18n.feature +0 -18
- data/features/support/paths.rb +0 -65
- data/lib/netzke/basepack/form_panel/javascripts/display_mode.js +0 -68
- data/lib/netzke/basepack/form_panel/javascripts/netzkefileupload.js +0 -5
- data/test/rails_app/spec/controllers/embedded_components_controller_spec.rb +0 -12
- data/test/rails_app/spec/helpers/embedded_components_helper_spec.rb +0 -15
- data/test/rails_app/spec/models/address_spec.rb +0 -5
- data/test/rails_app/spec/models/author_spec.rb +0 -5
- data/test/rails_app/spec/models/book_spec.rb +0 -5
- data/test/rails_app/spec/models/role_spec.rb +0 -5
- data/test/rails_app/spec/models/user_spec.rb +0 -5
- data/test/rails_app/spec/views/embedded_components/index.html.erb_spec.rb +0 -5
data/CHANGELOG.rdoc
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
= v0.6.5 - 2011-08-16
|
|
2
|
+
* changes
|
|
3
|
+
* Replaced tri-state checkbox with combobox in the multi-edit form and search form
|
|
4
|
+
* enhancements
|
|
5
|
+
* When columns states are saved in the persistent storage, adding/removing columns (e.g. in the code) will reset the saved states
|
|
6
|
+
* Moved features and specs to test/rails_app
|
|
7
|
+
* bug fix
|
|
8
|
+
* FormPanel with multiple association fields wouldn't submit data correctly
|
|
9
|
+
* Fixed an old bug where tri-checkbox set to 'unchecked' had no effect in multi-edit
|
|
10
|
+
|
|
1
11
|
= v0.6.4 - 2011-02-26
|
|
2
12
|
* API changes
|
|
3
13
|
* The combo field able to talk to the server has changed its xtype from combobox to netzkeremotecombo. When getting values from the server via AJAX, it expects a 2-dimensional array now, where the first value is the real value (which gets submitted), and the second value is the display value.
|
data/README.rdoc
CHANGED
|
@@ -35,7 +35,7 @@ For more examples, see http://demo.netzke.com, and look into test/rails_app
|
|
|
35
35
|
|
|
36
36
|
Netzke-basepack is bundled with automated tests. To run them, you need to set up test/rails_app a similar way as you did with your own Rails app that is using Netzke, i.e.: 1) link Ext JS into the "public" folder, 2) link your copy of netzke-core and netzke-basepack into vendor/gems, 3) run migrations and clone the development database structure into the test database.
|
|
37
37
|
|
|
38
|
-
After this you may run (*from
|
|
38
|
+
After this you may run (*from test/rails_app*):
|
|
39
39
|
|
|
40
40
|
cucumber features
|
|
41
41
|
|
data/Rakefile
CHANGED
|
@@ -9,7 +9,7 @@ begin
|
|
|
9
9
|
gemspec.email = "sergei@playcode.nl"
|
|
10
10
|
gemspec.homepage = "http://netzke.org"
|
|
11
11
|
gemspec.authors = ["Sergei Kozlov"]
|
|
12
|
-
gemspec.add_dependency("netzke-core", "~>0.6.
|
|
12
|
+
gemspec.add_dependency("netzke-core", "~>0.6.7")
|
|
13
13
|
gemspec.add_dependency("meta_where", ">=0.9.3")
|
|
14
14
|
gemspec.add_dependency("will_paginate", "~>3.0.pre2")
|
|
15
15
|
gemspec.add_dependency("acts_as_list")
|
data/javascripts/basepack.js
CHANGED
|
@@ -108,114 +108,10 @@ Ext.grid.HeaderDropZone.prototype.onNodeDrop = function(n, dd, e, data){
|
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
Ext.ns('Ext.ux.form');
|
|
111
|
-
Ext.ux.form.TriCheckbox = Ext.extend(Ext.form.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
overClass: 'x-form-check-over',
|
|
116
|
-
clickClass: 'x-form-check-down',
|
|
117
|
-
triState: true,
|
|
118
|
-
defaultAutoCreate: {tag: 'input', type: 'hidden', autocomplete: 'off'},
|
|
119
|
-
initComponent: function() {
|
|
120
|
-
this.value = this.checked;
|
|
121
|
-
Ext.ux.form.TriCheckbox.superclass.initComponent.apply(this, arguments);
|
|
122
|
-
// make a copy before modifying valueList and stateClassList arrays
|
|
123
|
-
this.vList = this.valueList.slice(0);
|
|
124
|
-
this.cList = this.stateClassList.slice(0);
|
|
125
|
-
if(this.triState !== true) {
|
|
126
|
-
// consider 'undefined' value and its class go first in arrays
|
|
127
|
-
this.vList.shift();
|
|
128
|
-
this.cList.shift();
|
|
129
|
-
}
|
|
130
|
-
if(this.overCls !== undefined) {
|
|
131
|
-
this.overClass = this.overCls;
|
|
132
|
-
delete this.overCls;
|
|
133
|
-
}
|
|
134
|
-
this.value = this.normalizeValue(this.value);
|
|
135
|
-
},
|
|
136
|
-
onRender : function(ct, position){
|
|
137
|
-
Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
|
|
138
|
-
|
|
139
|
-
this.innerWrap = this.el.wrap({tag: 'span', cls: 'x-form-check-innerwrap'});
|
|
140
|
-
this.wrap = this.innerWrap.wrap({cls: 'x-form-check-wrap'});
|
|
141
|
-
|
|
142
|
-
this.currCls = this.getCls(this.value);
|
|
143
|
-
this.wrap.addClass(this.currCls);
|
|
144
|
-
if(this.clickClass && !this.disabled && !this.readOnly)
|
|
145
|
-
this.innerWrap.addClassOnClick(this.clickClass);
|
|
146
|
-
if(this.overClass && !this.disabled && !this.readOnly)
|
|
147
|
-
this.innerWrap.addClassOnOver(this.overClass);
|
|
148
|
-
|
|
149
|
-
this.imageEl = this.innerWrap.createChild({
|
|
150
|
-
tag: 'img',
|
|
151
|
-
src: Ext.BLANK_IMAGE_URL,
|
|
152
|
-
cls: 'x-form-tscheckbox'
|
|
153
|
-
}, this.el);
|
|
154
|
-
if(this.fieldClass) this.imageEl.addClass(this.fieldClass);
|
|
155
|
-
|
|
156
|
-
if(this.boxLabel){
|
|
157
|
-
this.innerWrap.createChild({
|
|
158
|
-
tag: 'label',
|
|
159
|
-
htmlFor: this.el.id,
|
|
160
|
-
cls: 'x-form-cb-label',
|
|
161
|
-
html: this.boxLabel
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Need to repaint for IE, otherwise positioning is broken
|
|
166
|
-
if(Ext.isIE){
|
|
167
|
-
this.wrap.repaint();
|
|
168
|
-
}
|
|
169
|
-
this.resizeEl = this.positionEl = this.wrap;
|
|
170
|
-
},
|
|
171
|
-
onResize : function(){
|
|
172
|
-
Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
|
|
173
|
-
if(!this.boxLabel && !this.fieldLabel && this.imageEl){
|
|
174
|
-
this.imageEl.alignTo(this.wrap, 'c-c');
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
initEvents : function(){
|
|
178
|
-
Ext.form.Checkbox.superclass.initEvents.call(this);
|
|
179
|
-
this.mon(this.innerWrap, {
|
|
180
|
-
scope: this,
|
|
181
|
-
click: this.onClick
|
|
182
|
-
});
|
|
183
|
-
},
|
|
184
|
-
onClick : function(){
|
|
185
|
-
if (!this.disabled && !this.readOnly) {
|
|
186
|
-
this.setValue(this.vList[(this.vList.indexOf(this.value) + 1) % this.vList.length]);
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
getValue : function(){
|
|
190
|
-
return this.value;
|
|
191
|
-
},
|
|
192
|
-
setValue : function(v){
|
|
193
|
-
var value = this.value;
|
|
194
|
-
this.value = this.normalizeValue(v);
|
|
195
|
-
if(this.rendered) this.el.dom.value = this.value;
|
|
196
|
-
|
|
197
|
-
if(value !== this.value){
|
|
198
|
-
this.updateView();
|
|
199
|
-
this.fireEvent('check', this, this.value);
|
|
200
|
-
if(this.handler) this.handler.call(this.scope || this, this, this.value);
|
|
201
|
-
}
|
|
202
|
-
return this;
|
|
203
|
-
},
|
|
204
|
-
normalizeValue: function(v) {
|
|
205
|
-
return (v === null || v === undefined) && this.triState ? null :
|
|
206
|
-
(v === true || (['true', 'yes', 'on', '1']).indexOf(String(v).toLowerCase()) != -1);
|
|
207
|
-
},
|
|
208
|
-
getCls: function(v) {
|
|
209
|
-
var idx = this.vList.indexOf(this.value);
|
|
210
|
-
return idx > -1 ? this.cList[idx] : undefined;
|
|
211
|
-
},
|
|
212
|
-
updateView: function() {
|
|
213
|
-
var cls = this.getCls(this.value);
|
|
214
|
-
if (!this.wrap || cls === undefined) return;
|
|
215
|
-
|
|
216
|
-
this.wrap.replaceClass(this.currCls, cls);
|
|
217
|
-
this.currCls = cls;
|
|
218
|
-
}
|
|
111
|
+
Ext.ux.form.TriCheckbox = Ext.extend(Ext.form.ComboBox, {
|
|
112
|
+
store: [[true, "true"], [false, "false"]],
|
|
113
|
+
forceSelection: true,
|
|
114
|
+
triggerAction: 'all'
|
|
219
115
|
});
|
|
220
116
|
Ext.reg('tricheckbox', Ext.ux.form.TriCheckbox);
|
|
221
117
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Feedback Ghost
|
|
2
|
+
Netzke.FeedbackGhost = function(){};
|
|
3
|
+
Ext.apply(Netzke.FeedbackGhost.prototype, {
|
|
4
|
+
showFeedback: function(msg){
|
|
5
|
+
var createBox = function(s, l){
|
|
6
|
+
return ['<div class="msg">',
|
|
7
|
+
'<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>',
|
|
8
|
+
'<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">', s, '</div></div></div>',
|
|
9
|
+
'<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>',
|
|
10
|
+
'</div>'].join('');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
var showBox = function(msg, lvl){
|
|
14
|
+
if (!lvl) {lvl = 'notice'};
|
|
15
|
+
|
|
16
|
+
var msgCt = Ext.get('netzke-feedback') || Ext.DomHelper.insertFirst(document.body, {id: 'netzke-feedback', 'class':'netzke-feedback'}, true);
|
|
17
|
+
|
|
18
|
+
var m = Ext.DomHelper.append(msgCt, {html:createBox(msg,lvl)}, true);
|
|
19
|
+
m.slideIn('t').pause(2).ghost("b", {remove:true});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof msg != 'string') {
|
|
23
|
+
var compoundMsg = "";
|
|
24
|
+
Ext.each(msg, function(m){
|
|
25
|
+
compoundMsg += m.msg + '<br>';
|
|
26
|
+
});
|
|
27
|
+
if (compoundMsg != "") showBox(compoundMsg, null); // the second parameter will be level
|
|
28
|
+
} else {
|
|
29
|
+
showBox(msg);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
Netzke.componentMixin.feedbackGhost = new Netzke.FeedbackGhost();
|
data/lib/netzke/basepack.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Netzke
|
|
|
11
11
|
|
|
12
12
|
# Called from netzke-basepack.rb
|
|
13
13
|
def init
|
|
14
|
+
Netzke::Core.ext_javascripts << "#{File.dirname(__FILE__)}/../../javascripts/feedback_ghost.js"
|
|
14
15
|
Netzke::Core.ext_javascripts << "#{File.dirname(__FILE__)}/../../javascripts/datetimefield.js"
|
|
15
16
|
Netzke::Core.ext_javascripts << "#{File.dirname(__FILE__)}/../../javascripts/basepack.js"
|
|
16
17
|
|
|
@@ -71,16 +71,17 @@ module Netzke
|
|
|
71
71
|
c[:bbar] = [:apply.action] if c[:bbar].nil?
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
# Extra
|
|
74
|
+
# Extra JavaScripts and stylesheets
|
|
75
75
|
js_mixin :form_panel
|
|
76
76
|
js_include :comma_list_cbg
|
|
77
|
-
js_include :n_radio_group, :
|
|
78
|
-
# Netzke::Base.config[:ext_location] + "/examples/ux/fileuploadfield/FileUploadField.js",
|
|
79
|
-
# "#{File.dirname(__FILE__)}/form_panel/javascripts/netzkefileupload.js"
|
|
80
|
-
|
|
81
|
-
# Extra CSS
|
|
77
|
+
js_include :n_radio_group, :readonly_mode
|
|
82
78
|
css_include :readonly_mode
|
|
83
79
|
|
|
80
|
+
js_include Netzke::Core.ext_location.join("examples/ux/fileuploadfield/FileUploadField.js")
|
|
81
|
+
css_include Netzke::Core.ext_location.join("examples/ux/fileuploadfield/css/fileuploadfield.css")
|
|
82
|
+
|
|
83
|
+
js_include :misc
|
|
84
|
+
|
|
84
85
|
def js_config
|
|
85
86
|
super.tap do |res|
|
|
86
87
|
res[:pri] = data_class && data_class.primary_key
|
|
@@ -98,11 +98,8 @@ module Netzke
|
|
|
98
98
|
detect_association_with_method(field) # xtype for an association field
|
|
99
99
|
set_default_field_label(field)
|
|
100
100
|
set_default_field_xtype(field) if field[:xtype].nil?
|
|
101
|
-
# set_default_field_value(field) if self.record
|
|
102
101
|
set_default_read_only(field)
|
|
103
102
|
|
|
104
|
-
field[:display_mode] = config[:display_mode] if config[:display_mode]
|
|
105
|
-
|
|
106
103
|
# provide our special combobox with our id
|
|
107
104
|
field[:parent_id] = self.global_id if field[:xtype] == :netzkeremotecombo
|
|
108
105
|
|
|
@@ -153,17 +150,6 @@ module Netzke
|
|
|
153
150
|
item.is_a?(String) || item.is_a?(Symbol) || item[:name] # && !is_component_config?(item)
|
|
154
151
|
end
|
|
155
152
|
|
|
156
|
-
def set_default_field_label(c)
|
|
157
|
-
# multiple spaces (in case of association attrs) get replaced with one
|
|
158
|
-
c[:field_label] ||= data_class ? data_class.human_attribute_name(c[:name]) : c[:name].humanize
|
|
159
|
-
c[:field_label].gsub!(/\s+/, " ")
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
# def set_default_field_value(field)
|
|
163
|
-
# value = record.value_for_attribute(field)
|
|
164
|
-
# field[:value] ||= value unless value.nil?
|
|
165
|
-
# end
|
|
166
|
-
|
|
167
153
|
# Deeply merges only those key/values at the top level that are already there
|
|
168
154
|
def deep_merge_existing_fields(dest, src)
|
|
169
155
|
dest.each_pair do |k,v|
|
|
@@ -171,6 +157,12 @@ module Netzke
|
|
|
171
157
|
end
|
|
172
158
|
end
|
|
173
159
|
|
|
160
|
+
def set_default_field_label(c)
|
|
161
|
+
# multiple spaces (in case of association attrs) get replaced with one
|
|
162
|
+
c[:field_label] ||= data_class ? data_class.human_attribute_name(c[:name]) : c[:name].humanize
|
|
163
|
+
c[:field_label].gsub!(/\s+/, " ")
|
|
164
|
+
end
|
|
165
|
+
|
|
174
166
|
def set_default_field_xtype(field)
|
|
175
167
|
field[:xtype] = xtype_for_attr_type(field[:attr_type]) unless xtype_for_attr_type(field[:attr_type]).nil?
|
|
176
168
|
end
|
|
@@ -19,6 +19,19 @@
|
|
|
19
19
|
initComponent: function(){
|
|
20
20
|
if (!this.bbar) this.bbar = {xtype: 'toolbar'}; // an empty bbar by default, so that we can dynamically add buttons
|
|
21
21
|
|
|
22
|
+
// Custom error reader. We don't use it to process form values, but rather to normalize the response from the server in case of "real" (iframe) form submit.
|
|
23
|
+
ErrorReader = function(){};
|
|
24
|
+
|
|
25
|
+
ErrorReader.prototype.read = function(xhr) {
|
|
26
|
+
var unescapeHTML = function(str) {
|
|
27
|
+
return str.replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
|
|
28
|
+
}
|
|
29
|
+
xhr.responseText = unescapeHTML(xhr.responseText.replace(/<pre.*?>/, "").replace("</pre>", ""));
|
|
30
|
+
return {records: [], success: true};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
this.initialConfig.errorReader = new ErrorReader();
|
|
34
|
+
|
|
22
35
|
// Now let Ext.form.FormPanel do the rest
|
|
23
36
|
Netzke.classes.Basepack.FormPanel.superclass.initComponent.call(this);
|
|
24
37
|
|
|
@@ -73,40 +86,63 @@
|
|
|
73
86
|
tbar.doLayout();
|
|
74
87
|
},
|
|
75
88
|
|
|
76
|
-
|
|
77
89
|
onApply: function() {
|
|
78
90
|
if (this.fireEvent('apply', this)) {
|
|
79
91
|
var values = this.getForm().getFieldValues();
|
|
80
92
|
|
|
81
|
-
// do not send values from disabled fields and empty values
|
|
82
93
|
for (var fieldName in values) {
|
|
83
94
|
var field = this.getForm().findField(fieldName);
|
|
95
|
+
|
|
96
|
+
// TODO: move the following checks to the server side (through the :display_only option)
|
|
97
|
+
|
|
98
|
+
// do not submit values from disabled fields
|
|
84
99
|
if (!field || field.disabled) delete values[fieldName];
|
|
100
|
+
|
|
101
|
+
// do not submit values from read-only association fields
|
|
102
|
+
if (field
|
|
103
|
+
&& field.name.indexOf("__") !== -1
|
|
104
|
+
&& (field.readOnly || !field.getStore)
|
|
105
|
+
&& (!field.nestedAttribute) // except for "nested attributes"
|
|
106
|
+
) delete values[fieldName];
|
|
107
|
+
|
|
108
|
+
// do not submit values from displayfields
|
|
109
|
+
if (field.isXType('displayfield')) delete values[fieldName];
|
|
110
|
+
|
|
111
|
+
// do not submit displayOnly fields
|
|
112
|
+
if (field.displayOnly) delete values[fieldName];
|
|
85
113
|
}
|
|
86
114
|
|
|
115
|
+
// apply mask
|
|
87
116
|
if (!this.applyMaskCmp) this.applyMaskCmp = new Ext.LoadMask(this.bwrap, this.applyMask);
|
|
88
|
-
|
|
89
117
|
this.applyMaskCmp.show();
|
|
90
118
|
|
|
119
|
+
// We must use a different approach when the form is multipart, as we can't use the endpoint
|
|
91
120
|
if (this.fileUpload) {
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
api: {submit: Netzke.providers[this.parentId].netzkeSubmit},
|
|
121
|
+
this.getForm().submit({ // normal submit
|
|
122
|
+
url: this.endpointUrl("netzke_submit"),
|
|
95
123
|
params: {
|
|
96
|
-
data: Ext.encode(values)
|
|
124
|
+
data: Ext.encode(values) // here are the correct values that may be different from display values
|
|
97
125
|
},
|
|
98
126
|
failure: function(form, action){
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
127
|
+
if (this.applyMaskCmp) this.applyMaskCmp.hide();
|
|
128
|
+
},
|
|
129
|
+
success: function(form, action) {
|
|
130
|
+
try {
|
|
131
|
+
var respObj = Ext.decode(action.response.responseText);
|
|
132
|
+
delete respObj.success;
|
|
133
|
+
this.bulkExecute(respObj);
|
|
134
|
+
this.fireEvent('submitsuccess');
|
|
135
|
+
}
|
|
136
|
+
catch(e) {
|
|
137
|
+
Ext.Msg.alert('File upload error', action.response.responseText);
|
|
138
|
+
}
|
|
102
139
|
if (this.applyMaskCmp) this.applyMaskCmp.hide();
|
|
103
140
|
},
|
|
104
141
|
scope: this
|
|
105
142
|
});
|
|
106
143
|
} else {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (result === "ok") {
|
|
144
|
+
this.netzkeSubmit(Ext.apply((this.baseParams || {}), {data:Ext.encode(values)}), function(success){
|
|
145
|
+
if (success) {
|
|
110
146
|
this.fireEvent("submitsuccess");
|
|
111
147
|
if (this.mode == "lockable") this.setReadonlyMode(true);
|
|
112
148
|
};
|
|
@@ -120,28 +156,18 @@
|
|
|
120
156
|
var assocValues = values._meta.associationValues || {};
|
|
121
157
|
for (var assocFieldName in assocValues) {
|
|
122
158
|
var assocField = this.find('name', assocFieldName)[0];
|
|
123
|
-
if (
|
|
124
|
-
assocField.origValue = values[assocFieldName];
|
|
125
|
-
assocField.setValue(assocValues[assocFieldName]);
|
|
126
|
-
delete values[assocFieldName]; // we don't want this to be set once more below with setValues()
|
|
127
|
-
} else {
|
|
159
|
+
if (assocField.getStore) {
|
|
128
160
|
assocField.getStore().loadData({data: [[values[assocFieldName], assocValues[assocFieldName]]]});
|
|
129
161
|
delete assocField.lastQuery; // force loading the store next time user clicks the trigger
|
|
162
|
+
} else {
|
|
163
|
+
assocField.setValue(assocValues[assocFieldName]);
|
|
164
|
+
delete values[assocFieldName]; // we don't want this to be set once more below with setValues()
|
|
130
165
|
}
|
|
131
166
|
}
|
|
132
167
|
|
|
133
168
|
this.getForm().setValues(values);
|
|
134
169
|
},
|
|
135
170
|
|
|
136
|
-
setDisplayMode: function(onOff, cancel){
|
|
137
|
-
if (this.inDisplayMode == onOff) return;
|
|
138
|
-
this.getForm().items.each(function(i){i.setDisplayMode(onOff);});
|
|
139
|
-
this.getForm().cleanDestroyed(); // because fields inside of composite fields are not auto-cleaned!
|
|
140
|
-
this.doLayout();
|
|
141
|
-
this.inDisplayMode = onOff;
|
|
142
|
-
this.updateToolbar();
|
|
143
|
-
},
|
|
144
|
-
|
|
145
171
|
setReadonlyMode: function(onOff, cancel){
|
|
146
172
|
if (this.inReadonlyMode == onOff) return;
|
|
147
173
|
this.getForm().items.each(function(i){i.setReadonlyMode(onOff);});
|
|
@@ -4,7 +4,9 @@ Ext.override(Ext.form.Field, {
|
|
|
4
4
|
setReadonlyMode: function(onOff){
|
|
5
5
|
if (this.hidden) return;
|
|
6
6
|
|
|
7
|
-
this.
|
|
7
|
+
if (!this.initialConfig.readOnly) {
|
|
8
|
+
this.setReadOnly(onOff);
|
|
9
|
+
}
|
|
8
10
|
|
|
9
11
|
if (onOff) {
|
|
10
12
|
this.addClass("readonly");
|
|
@@ -13,26 +15,7 @@ Ext.override(Ext.form.Field, {
|
|
|
13
15
|
this.removeClass("readonly");
|
|
14
16
|
if (this.label) this.label.removeClass("readonly");
|
|
15
17
|
}
|
|
16
|
-
|
|
17
|
-
// var newConfig = this.readonlyModeConfig(onOff);
|
|
18
|
-
//
|
|
19
|
-
// var idx = this.removeSelf();
|
|
20
|
-
// owner.insert(idx, newConfig);
|
|
21
|
-
//
|
|
22
|
-
// this.destroy();
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
// Remove self from the container
|
|
26
|
-
// removeSelf: function(){
|
|
27
|
-
// var idx = this.ownerCt.items.indexOf(this);
|
|
28
|
-
// this.ownerCt.remove(this);
|
|
29
|
-
// return idx;
|
|
30
|
-
// },
|
|
31
|
-
|
|
32
|
-
// Config for creating an instance in "displayMode" (if onOff is true), or normal mode (if onOff is false)
|
|
33
|
-
// displayModeConfig: function(onOff){
|
|
34
|
-
// return Ext.apply(this.initialConfig, onOff ? {xtype: 'displayfield', origXtype: this.xtype, value: this.getValue()} : {xtype: this.origXtype, value: this.getValue()});
|
|
35
|
-
// }
|
|
18
|
+
}
|
|
36
19
|
|
|
37
20
|
});
|
|
38
21
|
|
|
@@ -9,7 +9,7 @@ module Netzke
|
|
|
9
9
|
#
|
|
10
10
|
# Endpoints
|
|
11
11
|
#
|
|
12
|
-
endpoint :netzke_submit do |params|
|
|
12
|
+
endpoint :netzke_submit, :pre => true do |params|
|
|
13
13
|
netzke_submit(params)
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -48,16 +48,23 @@ module Netzke
|
|
|
48
48
|
# Implementation for the "netzke_submit" endpoint (for backward compatibility)
|
|
49
49
|
def netzke_submit(params)
|
|
50
50
|
data = ActiveSupport::JSON.decode(params[:data])
|
|
51
|
+
|
|
52
|
+
# File uploads are in raw params instead of "data" hash, so, mix them in into "data"
|
|
53
|
+
if config[:file_upload]
|
|
54
|
+
Netzke::Core.controller.params.each_pair do |k,v|
|
|
55
|
+
data[k] = v if v.is_a?(ActionDispatch::Http::UploadedFile)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
51
59
|
success = create_or_update_record(data)
|
|
52
60
|
|
|
53
61
|
if success
|
|
54
|
-
{:set_form_values => js_record_data, :set_result =>
|
|
62
|
+
{:set_form_values => js_record_data, :set_result => true}
|
|
55
63
|
else
|
|
56
64
|
# flash eventual errors
|
|
57
65
|
@record.errors.to_a.each do |msg|
|
|
58
66
|
flash :error => msg
|
|
59
67
|
end
|
|
60
|
-
# {:feedback => @flash}
|
|
61
68
|
{:feedback => @flash, :apply_form_errors => build_form_errors(record)}
|
|
62
69
|
end
|
|
63
70
|
end
|