netzke-basepack 0.6.4 → 0.6.5

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