netzke-basepack 0.12.0 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,3 @@
1
- require "netzke/basepack/form/services"
2
-
3
1
  module Netzke
4
2
  module Basepack
5
3
  # Ext.form.Panel-based component
@@ -28,6 +26,7 @@ module Netzke
28
26
  # * +netzke_submit+ - gets called when the form gets submitted (e.g. by pressing the Apply button, or by calling onApply)
29
27
  # * +get_combobox_options+ - gets called when a 'remote' combobox field gets expanded
30
28
  class Form < Netzke::Base
29
+ include self::Endpoints
31
30
  include self::Services
32
31
  include Fields
33
32
  include DataAccessor
@@ -0,0 +1,35 @@
1
+ module Netzke
2
+ module Basepack
3
+ class Form < Netzke::Base
4
+ module Endpoints
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ # Called when the form gets submitted (e.g. by pressing the Apply button)
9
+ endpoint :netzke_submit do |params, this|
10
+ data = ActiveSupport::JSON.decode(params[:data])
11
+ submit(data, this)
12
+ end
13
+
14
+ # Can be called when the form needs to load a record with given ID. E.g.:
15
+ #
16
+ # someForm.netzkeLoad({id: 100});
17
+ endpoint :netzke_load do |params, this|
18
+ @record = data_class && data_adapter.find_record(params[:id])
19
+ this.set_form_values js_record_data
20
+ end
21
+
22
+ # Returns options for a combobox
23
+ # params receive:
24
+ # +attr+ - column's name
25
+ # +query+ - what's typed-in in the combobox
26
+ # +id+ - selected record id
27
+ endpoint :get_combobox_options do |params, this|
28
+ attr = fields[params[:attr].to_sym]
29
+ this.data = data_adapter.combo_data(attr, params[:query])
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -4,65 +4,33 @@ module Netzke
4
4
  module Services
5
5
  extend ActiveSupport::Concern
6
6
 
7
- included do
8
- #
9
- # Endpoints
10
-
11
- # Called when the form gets submitted (e.g. by pressing the Apply button)
12
- endpoint :netzke_submit do |params, this|
13
- data = ActiveSupport::JSON.decode(params[:data])
14
- data.each_pair do |k,v|
15
- # Ext JS returns "null" on empty date fields, or "" for not filled optional integer fields, which gives
16
- # errors when passed to model (at least in DataMapper)
17
- data[k]=nil if v == "" || v == "null"
18
- end
19
-
20
- # File uploads are in raw params instead of "data" hash, so, mix them in into "data"
21
- controller.params.each_pair do |k,v|
22
- data[k] = v if v.is_a?(ActionDispatch::Http::UploadedFile)
23
- end
24
-
25
- success = create_or_update_record(data)
26
-
27
- if success
28
- this.set_form_values(js_record_data)
29
- this.success = true # respond to classic form submission with {success: true}
30
- this.on_submit_success # inform the Netzke endpoint caller about success
31
- else
32
- # flash eventual errors
33
- data_adapter.errors_array(@record).each do |error|
34
- flash :error => error
35
- end
36
- this.netzke_feedback(@flash)
37
- this.apply_form_errors(build_form_errors(record))
38
- end
7
+ def submit(data, this)
8
+ # File uploads are in raw params instead of "data" hash, so, mix them in into "data"
9
+ controller.params.each_pair do |k,v|
10
+ data[k] = v if v.is_a?(ActionDispatch::Http::UploadedFile)
39
11
  end
40
12
 
41
- # Can be called when the form needs to load a record with given ID. E.g.:
42
- #
43
- # someForm.netzkeLoad({id: 100});
44
- endpoint :netzke_load do |params, this|
45
- @record = data_class && data_adapter.find_record(params[:id])
46
- this.set_form_values js_record_data
47
- end
13
+ success = create_or_update_record(data)
48
14
 
49
- # Returns options for a combobox
50
- # params receive:
51
- # +attr+ - column's name
52
- # +query+ - what's typed-in in the combobox
53
- # +id+ - selected record id
54
- endpoint :get_combobox_options do |params, this|
55
- attr = fields[params[:attr].to_sym]
56
- this.data = data_adapter.combo_data(attr, params[:query])
15
+ if success
16
+ this.set_form_values(js_record_data)
17
+ this.success = true # respond to classic form submission with {success: true}
18
+ this.on_submit_success # inform the Netzke endpoint caller about success
19
+ else
20
+ # flash eventual errors
21
+ data_adapter.errors_array(@record).each do |error|
22
+ flash :error => error
23
+ end
24
+ this.netzke_feedback(@flash)
25
+ this.apply_form_errors(build_form_errors(record))
57
26
  end
58
-
59
27
  end
60
28
 
61
29
  def values
62
30
  record && record.netzke_hash(fields)
63
31
  end
64
32
 
65
- private
33
+ private
66
34
 
67
35
  # Builds the form errors
68
36
  def build_form_errors(record)
@@ -88,7 +56,7 @@ module Netzke
88
56
  def create_or_update_record(hsh)
89
57
  hsh.merge!(config[:strong_default_attrs]) if config[:strong_default_attrs]
90
58
  @record ||= data_adapter.find_record hsh.delete(data_class.primary_key.to_s) # only pick up the record specified in the params if it was not provided in the configuration
91
- #data_class.find(:first, :conditions => {data_class.primary_key => hsh.delete(data_class.primary_key)})
59
+ #data_class.find(:first, :conditions => {data_class.primary_key => hsh.delete(data_class.primary_key)})
92
60
  success = true
93
61
 
94
62
  @record = data_class.new if @record.nil?
@@ -97,20 +65,9 @@ module Netzke
97
65
  data_adapter.set_record_value_for_attribute(@record, fields[k.to_sym].nil? ? {:name => k} : fields[k.to_sym], v, config.role || :default)
98
66
  end
99
67
 
100
- #hsh.each_pair do |k,v|
101
- #begin
102
- #@record.send("#{k}=",v)
103
- #rescue StandardError => exc
104
- #flash :error => exc.message
105
- #success = false
106
- #break
107
- #end
108
- #end
109
-
110
68
  # did we have complete success?
111
69
  success && data_adapter.save_record(@record)
112
70
  end
113
-
114
71
  end
115
72
  end
116
73
  end
@@ -1,10 +1,6 @@
1
- require "netzke/basepack/grid/services"
2
- require 'netzke/basepack/column_config'
3
-
4
1
  module Netzke
5
2
  module Basepack
6
- # {Ext.grid.Panel}[http://docs.sencha.com/ext-js/4-1/#!/api/Ext.grid.Panel] -based component with the following
7
- # features:
3
+ # Ext.grid.Panel-based component with the following features:
8
4
  #
9
5
  # * automatic column configuration based on used ORM
10
6
  # * pagination
@@ -368,11 +364,14 @@ module Netzke
368
364
  # JavaScript class configuration
369
365
  js_configure do |c|
370
366
  c.extend = "Ext.grid.Panel"
371
- c.mixin :grid, :event_handling
367
+ c.mixin :grid
372
368
  c.mixin :advanced_search if advanced_search_available
373
369
  c.mixin :edit_in_form if edit_in_form_available
374
370
  c.mixin :remember_selection if remember_selection_available
375
371
 
372
+ c.mixins << "Netzke.mixins.Basepack.Columns"
373
+ c.mixins << "Netzke.mixins.Basepack.GridEventHandlers"
374
+
376
375
  c.translate *%w[are_you_sure confirmation]
377
376
 
378
377
  # JavaScript includes
@@ -466,7 +465,7 @@ module Netzke
466
465
 
467
466
  action :add do |a|
468
467
  a.disabled = config[:prohibit_create]
469
- a.handler = "onAddInline" # overriding naming conventions as Ext 4 grid has its own onAdd method
468
+ a.handler = "onAddRecord" # overriding naming conventions as Ext 4 grid has its own onAdd method
470
469
  a.icon = :add
471
470
  end
472
471
 
@@ -31,7 +31,6 @@ module Netzke
31
31
  # +query+ - what's typed-in in the combobox
32
32
  # +id+ - selected record id
33
33
  endpoint :get_combobox_options do |params, this|
34
- ::Rails.logger.debug "\n!!! params: #{params.inspect}\n"
35
34
  column = final_columns.detect{ |c| c[:name] == params[:attr] }
36
35
  this.data = data_adapter.combo_data(column, params[:query])
37
36
  end
@@ -23,6 +23,7 @@ Ext.define('Netzke.classes.Basepack.Grid.Proxy', {
23
23
  extend: 'Ext.data.proxy.Server',
24
24
 
25
25
  batch: function(options) {
26
+ console.log("options ", options);
26
27
  if (!options) return;
27
28
  for (operation in options.operations) {
28
29
  var op = new Ext.data.Operation({action: operation, records: options.operations[operation]});
@@ -32,6 +33,7 @@ Ext.define('Netzke.classes.Basepack.Grid.Proxy', {
32
33
 
33
34
  destroy: function(op, callback, scope) {
34
35
  var data = Ext.Array.map(op.getRecords(), function(r) { return r.getData().id; });
36
+ console.log("data ", data);
35
37
  var store = this.grid.getStore();
36
38
  this.grid.serverDelete(data, function(res){
37
39
  var errors = [];
@@ -1,9 +1,4 @@
1
1
  {
2
- trackMouseOver: true,
3
- loadMask: true,
4
- autoScroll: true,
5
-
6
- componentLoadMask: {msg: "Loading..."},
7
2
  multiSelect: true,
8
3
 
9
4
  initComponent: function(){
@@ -21,15 +16,8 @@
21
16
  // Normalize columns. Extract data fields and meta column.
22
17
  this.netzkeProcessColumns();
23
18
 
24
- // Define the model
25
- if (!Netzke.isModelDefined(this.id)) {
26
- Ext.define(Netzke.modelName(this.id), {
27
- extend: 'Ext.data.Model',
28
- idProperty: this.pri, // Primary key
29
- fields: this.fields
30
- });
31
- }
32
- delete this.pri;
19
+ this.netzkeBuildModel('Ext.data.Model');
20
+
33
21
  delete this.fields;
34
22
 
35
23
  // Prepare column model config with columns in the correct order; columns out of order go to the end.
@@ -113,9 +101,6 @@
113
101
  if (this.actions.edit) this.actions.edit.setDisabled(selModel.getCount() != 1 || this.prohibitUpdate);
114
102
  }, this);
115
103
 
116
- // WIP: GridView
117
- this.getView().getRowClass = this.netzkeDefaultGetRowClass;
118
-
119
104
  // When starting editing as assocition column, pre-load the combobox store from the meta column, so that we don't see the real value of this cell (the id of the associated record), but rather the associated record by the configured method.
120
105
  this.on('beforeedit', function(editor, e){
121
106
  if (e.column.assoc && e.record.get('meta') && e.column.getEditor()) {
@@ -165,73 +150,6 @@
165
150
  }
166
151
  },
167
152
 
168
- netzkeProcessColumns: function() {
169
- this.fields = [];
170
-
171
- // Run through columns and set up different configuration for each
172
- Ext.each(this.columns, function(c, i){
173
-
174
- this.netzkeNormalizeRenderer(c);
175
-
176
- // Build the field configuration for this column
177
- var fieldConfig = {name: c.name, defaultValue: c.defaultValue, useNull: true}; // useNull is needed to not convert nils to 0 in associations!
178
-
179
- if (c.name !== 'meta') fieldConfig.type = this.netzkeFieldTypeForAttrType(c.attrType); // field type (grid editors need this to function well)
180
-
181
- if (c.attrType == 'datetime') {
182
- fieldConfig.dateFormat = 'Y-m-d H:i:s'; // set the format in which we receive datetime from the server (so that the model can parse it)
183
-
184
- // While for 'date' columns the renderer is set up automatically (through using column's xtype), there's no appropriate xtype for our custom datetime column.
185
- // Thus, we need to set the renderer manually.
186
- // NOTE: for Ext there's no distinction b/w date and datetime; date fields can include time.
187
- if (!c.renderer) {
188
- // format in which the data will be rendered; if c.format is nil, Ext.Date.defaultFormat extended with time will be used
189
- c.renderer = Ext.util.Format.dateRenderer(c.format || Ext.Date.defaultFormat + " H:i:s");
190
- }
191
- };
192
-
193
- if (c.attrType == 'date') {
194
- // If no dateFormat given for date attrType, Timezone translation can subtract zone offset from 00:00:00 causing previous day.
195
- fieldConfig.dateFormat = 'Y-m-d';
196
- };
197
-
198
- // because checkcolumn doesn't care about editor (not) being set, we need to explicitely set readOnly here
199
- if (c.xtype == 'checkcolumn' && !c.editor) {
200
- c.readOnly = true;
201
- }
202
-
203
- this.fields.push(fieldConfig);
204
-
205
- // We will not use meta columns as actual columns (not even hidden) - only to create the records
206
- if (c.meta) {
207
- this.metaColumn = c;
208
- return;
209
- }
210
-
211
- // Set rendeder for association columns (the one displaying associations by the specified method instead of id)
212
- if (c.assoc) {
213
- // Editor for association column
214
- if (c.editor) c.editor = Ext.apply({ name: c.name }, c.editor);
215
-
216
- // Renderer for association column
217
- this.netzkeNormalizeAssociationRenderer(c);
218
- }
219
-
220
- if (c.editor) {
221
- Ext.applyIf(c.editor, {selectOnFocus: true, netzkeParent: this});
222
- }
223
-
224
- // Setting the default filter type
225
- if (c.filterable != false && !c.filter) {
226
- c.filter = {type: c.assoc ? 'string' : this.netzkeFilterTypeForAttrType(c.attrType)};
227
- }
228
-
229
- // setting dataIndex
230
- c.dataIndex = c.name;
231
-
232
- }, this);
233
- },
234
-
235
153
  netzkeBuildStore: function() {
236
154
  var store = Ext.create('Ext.data.Store', Ext.apply({
237
155
  model: Netzke.modelName(this.id),
@@ -261,124 +179,5 @@
261
179
 
262
180
  netzkeBuildReader: function() {
263
181
  return Ext.create('Netzke.classes.Basepack.Grid.ArrayReader');
264
- },
265
-
266
- netzkeFilterTypeForAttrType: function(attrType){
267
- var map = {
268
- integer : 'number',
269
- decimal : 'number',
270
- float : 'number',
271
- datetime : 'date',
272
- date : 'date',
273
- string : 'string',
274
- text : 'string',
275
- 'boolean' : 'boolean'
276
- };
277
- return map[attrType] || 'string';
278
- },
279
-
280
- netzkeFieldTypeForAttrType: function(attrType){
281
- var map = {
282
- integer : 'int',
283
- decimal : 'float',
284
- float : 'float',
285
- datetime : 'date',
286
- date : 'date',
287
- string : 'string',
288
- text : 'string',
289
- 'boolean' : 'boolean'
290
- };
291
- return map[attrType] || 'string';
292
- },
293
-
294
- // Tries editing the first editable (i.e. not hidden, not read-only) sell
295
- netzkeTryStartEditing: function(r){
296
- var editableIndex = 0;
297
- Ext.each(this.initialConfig.columns, function(c){
298
- // skip columns that cannot be edited
299
- if (!(c.hidden == true || !c.editor || c.attrType == 'boolean')) {
300
- return false;
301
- }
302
- editableIndex++;
303
- });
304
-
305
- if (editableIndex < this.initialConfig.columns.length) {this.getPlugin('celleditor').startEdit(r, this.columns[editableIndex]);}
306
- },
307
-
308
- netzkeDefaultGetRowClass: function(r){
309
- return r.isNew ? "grid-dirty-record" : ""
310
- },
311
-
312
- // Normalizes the renderer for a column.
313
- // Renderer may be:
314
- // 1) a string that contains the name of the function to be used as renderer.
315
- // 2) an array, where the first element is the function name, and the rest - the arguments
316
- // that will be passed to that function along with the value to be rendered.
317
- // The function is searched in the following objects: 1) Ext.util.Format, 2) this.
318
- // If not found, it is simply evaluated. Handy, when as renderer we receive an inline JS function,
319
- // or reference to a function in some other scope.
320
- // So, these will work:
321
- // * "uppercase"
322
- // * ["ellipsis", 10]
323
- // * ["substr", 3, 5]
324
- // * "myRenderer" (if this.myRenderer is a function)
325
- // * ["Some.scope.Format.customRenderer", 10, 20, 30] (if Some.scope.Format.customRenderer is a function)
326
- // * "function(v){ return 'Value: ' + v; }"
327
- netzkeNormalizeRenderer: function(c) {
328
- if (!c.renderer) return;
329
-
330
- var name, args = [];
331
-
332
- if ('string' === typeof c.renderer) {
333
- name = c.renderer.camelize(true);
334
- } else {
335
- name = c.renderer[0];
336
- args = c.renderer.slice(1);
337
- }
338
-
339
- // First check whether Ext.util.Format has it
340
- if (Ext.isFunction(Ext.util.Format[name])) {
341
- c.renderer = Ext.Function.bind(Ext.util.Format[name], this, args, 1);
342
- } else if (Ext.isFunction(this[name])) {
343
- // ... then if our own class has it
344
- c.renderer = Ext.Function.bind(this[name], this, args, 1);
345
- } else {
346
- // ... and, as last resort, evaluate it (allows passing inline javascript function as renderer)
347
- eval("c.renderer = " + c.renderer + ";");
348
- }
349
- },
350
-
351
- netzkeSaveColumns: function(){
352
- var cols = [];
353
- this.getView().getHeaderCt().items.each(function(c){
354
- cols.push({name: c.name, width: c.width, hidden: c.hidden});
355
- });
356
-
357
- this.serverSaveColumns(cols);
358
- },
359
-
360
- /*
361
- Set a renderer that displayes association values instead of association record ID.
362
- The association values are passed in the meta-column under associationValues hash.
363
- */
364
- netzkeNormalizeAssociationRenderer: function(c) {
365
- c.scope = this;
366
- var passedRenderer = c.renderer; // renderer we got from netzkeNormalizeRenderer
367
- c.renderer = function(value, a, r, ri, ci, store, view){
368
- var column = view.headerCt.items.getAt(ci),
369
- editor = column.getEditor && column.getEditor(),
370
- recordFromStore = editor && editor.isXType('combobox') && editor.getStore().findRecord('value', value),
371
- renderedValue;
372
-
373
- if (recordFromStore) {
374
- renderedValue = recordFromStore.get('text');
375
- } else if (c.assoc && r.get('meta')) {
376
- renderedValue = r.get('meta').associationValues[c.name] || c.emptyText;
377
- } else {
378
- renderedValue = value;
379
- }
380
-
381
- return passedRenderer ? passedRenderer.call(this, renderedValue) : renderedValue;
382
- };
383
182
  }
384
183
  }