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.
Files changed (77) hide show
  1. data/CHANGELOG.rdoc +10 -0
  2. data/README.rdoc +1 -1
  3. data/Rakefile +1 -1
  4. data/javascripts/basepack.js +4 -108
  5. data/javascripts/feedback_ghost.js +34 -0
  6. data/lib/netzke/basepack.rb +1 -0
  7. data/lib/netzke/basepack/form_panel.rb +7 -6
  8. data/lib/netzke/basepack/form_panel/fields.rb +6 -14
  9. data/lib/netzke/basepack/form_panel/javascripts/form_panel.js +53 -27
  10. data/lib/netzke/basepack/form_panel/javascripts/misc.js +4 -0
  11. data/lib/netzke/basepack/form_panel/javascripts/readonly_mode.js +4 -21
  12. data/lib/netzke/basepack/form_panel/services.rb +10 -3
  13. data/lib/netzke/basepack/grid_panel.rb +40 -26
  14. data/lib/netzke/basepack/grid_panel/columns.rb +25 -0
  15. data/lib/netzke/basepack/grid_panel/javascripts/grid_panel.js +4 -2
  16. data/lib/netzke/basepack/grid_panel/services.rb +10 -33
  17. data/lib/netzke/basepack/search_window.rb +2 -2
  18. data/lib/netzke/basepack/version.rb +1 -1
  19. data/netzke-basepack.gemspec +44 -145
  20. data/test/rails_app/Gemfile +3 -5
  21. data/test/rails_app/Gemfile.lock +78 -84
  22. data/test/rails_app/app/components/book_form.rb +12 -0
  23. data/test/rails_app/app/components/book_grid_with_scoped_authors.rb +8 -0
  24. data/test/rails_app/app/components/book_paging_form_panel.rb +3 -2
  25. data/test/rails_app/app/components/form_without_model.rb +2 -1
  26. data/test/rails_app/app/views/components/loadable_window.html.erb +9 -0
  27. data/test/rails_app/app/views/layouts/application.html.erb +1 -1
  28. data/test/rails_app/config/cucumber.yml +8 -0
  29. data/test/rails_app/config/{database.yml → database.yml.sample} +4 -1
  30. data/test/rails_app/config/locales/es.yml +4 -1
  31. data/{features → test/rails_app/features}/accordion_panel.feature +1 -4
  32. data/{features → test/rails_app/features}/components_in_view.feature +0 -0
  33. data/{features → test/rails_app/features}/form_panel.feature +18 -13
  34. data/{features → test/rails_app/features}/grid_panel.feature +0 -0
  35. data/test/rails_app/features/i18n.feature +18 -0
  36. data/{features → test/rails_app/features}/nested_attributes.feature +0 -0
  37. data/{features → test/rails_app/features}/paging_form_panel.feature +13 -1
  38. data/{features → test/rails_app/features}/search_in_grid.feature +0 -0
  39. data/{features → test/rails_app/features}/simple_app.feature +0 -0
  40. data/{features → test/rails_app/features}/simple_panel.feature +1 -5
  41. data/{features → test/rails_app/features}/step_definitions/accordion_steps.rb +0 -0
  42. data/{features → test/rails_app/features}/step_definitions/form_panel_steps.rb +1 -1
  43. data/{features → test/rails_app/features}/step_definitions/generic_steps.rb +0 -0
  44. data/{features → test/rails_app/features}/step_definitions/grid_panel_steps.rb +0 -0
  45. data/{features → test/rails_app/features}/step_definitions/pickle_steps.rb +0 -0
  46. data/{features → test/rails_app/features}/step_definitions/web_steps.rb +0 -0
  47. data/{features → test/rails_app/features}/support/env.rb +14 -13
  48. data/test/rails_app/features/support/paths.rb +24 -6
  49. data/{features → test/rails_app/features}/support/pickle.rb +0 -0
  50. data/test/rails_app/features/support/selectors.rb +39 -0
  51. data/{features → test/rails_app/features}/tab_panel.feature +1 -4
  52. data/{features → test/rails_app/features}/validations_in_grid.feature +0 -0
  53. data/{features → test/rails_app/features}/virtual_attributes.feature +0 -0
  54. data/{features → test/rails_app/features}/window.feature +0 -0
  55. data/test/rails_app/lib/tasks/cucumber.rake +71 -0
  56. data/test/rails_app/script/cucumber +10 -0
  57. data/{spec → test/rails_app/spec}/active_record/attributes_spec.rb +0 -0
  58. data/{spec → test/rails_app/spec}/active_record/relation_extensions_spec.rb +0 -0
  59. data/{spec → test/rails_app/spec}/components/form_panel_spec.rb +0 -0
  60. data/{spec → test/rails_app/spec}/components/grid_panel_spec.rb +0 -0
  61. data/{spec → test/rails_app/spec}/factories.rb +0 -0
  62. data/{spec → test/rails_app/spec}/spec_helper.rb +1 -6
  63. metadata +43 -141
  64. data/autotest/discover.rb +0 -3
  65. data/config/database.yml +0 -2
  66. data/features/i18n.feature +0 -18
  67. data/features/support/paths.rb +0 -65
  68. data/lib/netzke/basepack/form_panel/javascripts/display_mode.js +0 -68
  69. data/lib/netzke/basepack/form_panel/javascripts/netzkefileupload.js +0 -5
  70. data/test/rails_app/spec/controllers/embedded_components_controller_spec.rb +0 -12
  71. data/test/rails_app/spec/helpers/embedded_components_helper_spec.rb +0 -15
  72. data/test/rails_app/spec/models/address_spec.rb +0 -5
  73. data/test/rails_app/spec/models/author_spec.rb +0 -5
  74. data/test/rails_app/spec/models/book_spec.rb +0 -5
  75. data/test/rails_app/spec/models/role_spec.rb +0 -5
  76. data/test/rails_app/spec/models/user_spec.rb +0 -5
  77. data/test/rails_app/spec/views/embedded_components/index.html.erb_spec.rb +0 -5
@@ -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.
@@ -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 the netzke-basepack folder*):
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.4")
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")
@@ -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.Checkbox, {
112
- checked: null,
113
- valueList: [null, false, true],
114
- stateClassList: ['x-checkbox-undef', null, 'x-checkbox-checked'],
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();
@@ -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 javascripts
74
+ # Extra JavaScripts and stylesheets
75
75
  js_mixin :form_panel
76
76
  js_include :comma_list_cbg
77
- js_include :n_radio_group, :display_mode, :readonly_mode
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(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/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
- // Not a Netzke's standard endpoint call, because the form is multipart
93
- this.getForm().submit({
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
- // It will always be failure, as we don't play along with the Ext success indication (not returning {success: true})
100
- this.bulkExecute(Ext.decode(action.response.responseText));
101
- this.fireEvent('submitsuccess');
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
- // Submit the data and process the result
108
- this.netzkeSubmit(Ext.apply((this.baseParams || {}), {data:Ext.encode(values)}), function(result){
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 (this.inDisplayMode) {
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);});
@@ -0,0 +1,4 @@
1
+ Ext.override(Ext.ux.form.FileUploadField, {
2
+ // FormPanel won't submit this by default
3
+ displayOnly: true
4
+ });
@@ -4,7 +4,9 @@ Ext.override(Ext.form.Field, {
4
4
  setReadonlyMode: function(onOff){
5
5
  if (this.hidden) return;
6
6
 
7
- this.setReadOnly(onOff);
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
- // var owner = this.ownerCt;
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 => "ok"}
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