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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -547
- data/Gemfile +4 -1
- data/README.md +2 -1
- data/javascripts/basepack.js +9 -2
- data/javascripts/columns.js +224 -0
- data/{lib/netzke/basepack/grid/javascripts/event_handling.js → javascripts/mixins/grid_event_handlers.js} +58 -9
- data/lib/netzke/basepack.rb +1 -3
- data/lib/netzke/basepack/columns.rb +0 -2
- data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +18 -0
- data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +26 -29
- data/lib/netzke/basepack/form.rb +1 -2
- data/lib/netzke/basepack/form/endpoints.rb +35 -0
- data/lib/netzke/basepack/form/services.rb +18 -61
- data/lib/netzke/basepack/grid.rb +6 -7
- data/lib/netzke/basepack/grid/endpoints.rb +0 -1
- data/lib/netzke/basepack/grid/javascripts/extensions.js +2 -0
- data/lib/netzke/basepack/grid/javascripts/grid.js +2 -203
- data/lib/netzke/basepack/grid/services.rb +3 -1
- data/lib/netzke/basepack/search_panel.rb +7 -5
- data/lib/netzke/basepack/search_panel/javascripts/condition_field.js +1 -2
- data/lib/netzke/basepack/tree.rb +223 -0
- data/lib/netzke/basepack/tree/javascripts/extensions.js +101 -0
- data/lib/netzke/basepack/tree/javascripts/tree.js +112 -0
- data/lib/netzke/basepack/version.rb +1 -1
- data/locales/en.yml +18 -0
- metadata +8 -3
data/lib/netzke/basepack/form.rb
CHANGED
@@ -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
|
-
|
8
|
-
#
|
9
|
-
|
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
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/netzke/basepack/grid.rb
CHANGED
@@ -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
|
-
#
|
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
|
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 = "
|
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
|
-
|
25
|
-
|
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
|
}
|