netzke-basepack 0.3.1 → 0.3.3
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 +22 -0
- data/Manifest +6 -4
- data/README.rdoc +2 -2
- data/Rakefile +1 -1
- data/generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb +5 -6
- data/generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb +2 -1
- data/javascripts/basepack.js +2 -0
- data/lib/app/models/netzke_form_panel_field.rb +35 -3
- data/lib/app/models/netzke_grid_panel_column.rb +39 -2
- data/lib/netzke-basepack.rb +0 -1
- data/lib/netzke/accordion_panel.rb +51 -15
- data/lib/netzke/ar_ext.rb +14 -6
- data/lib/netzke/basic_app.rb +5 -5
- data/lib/netzke/border_layout_panel.rb +19 -4
- data/lib/netzke/container.rb +2 -6
- data/lib/netzke/db_fields.rb +40 -0
- data/lib/netzke/fields_configurator.rb +10 -18
- data/lib/netzke/form_panel.rb +42 -128
- data/lib/netzke/form_panel_extras/interface.rb +49 -0
- data/lib/netzke/form_panel_extras/js_builder.rb +131 -0
- data/lib/netzke/grid_panel.rb +20 -12
- data/lib/netzke/grid_panel_extras/interface.rb +181 -0
- data/lib/netzke/grid_panel_extras/js_builder.rb +322 -0
- data/lib/netzke/table_editor.rb +110 -0
- data/lib/netzke/wrapper.rb +1 -3
- data/netzke-basepack.gemspec +8 -8
- data/test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb +3 -1
- data/test/border_layout_panel_test.rb +8 -12
- data/test/grid_panel_test.rb +3 -3
- data/test/test_helper.rb +8 -0
- metadata +15 -11
- data/lib/netzke/column.rb +0 -50
- data/lib/netzke/grid_panel_interface.rb +0 -167
- data/lib/netzke/grid_panel_js_builder.rb +0 -298
- data/test/column_test.rb +0 -27
data/lib/netzke/grid_panel.rb
CHANGED
@@ -12,13 +12,17 @@ module Netzke
|
|
12
12
|
# * properties and column configuration
|
13
13
|
#
|
14
14
|
class GridPanel < Base
|
15
|
-
|
16
|
-
include GridPanelInterface
|
15
|
+
include_extras(__FILE__)
|
17
16
|
|
18
17
|
# define connection points between client side and server side of GridPanel. See implementation of equally named methods in the GridPanelInterface module.
|
19
18
|
interface :get_data, :post_data, :delete_data, :resize_column, :move_column, :get_cb_choices
|
20
19
|
|
20
|
+
include Netzke::DbFields
|
21
|
+
|
21
22
|
module ClassMethods
|
23
|
+
def widget_type
|
24
|
+
:grid
|
25
|
+
end
|
22
26
|
|
23
27
|
# Global GridPanel configuration
|
24
28
|
def config
|
@@ -51,7 +55,6 @@ module Netzke
|
|
51
55
|
:enable_column_filters => Netzke::Base.config[:grid_panel][:filters],
|
52
56
|
:enable_column_move => true,
|
53
57
|
:enable_column_resize => true,
|
54
|
-
:border => true,
|
55
58
|
:load_mask => true
|
56
59
|
},
|
57
60
|
:persistent_layout => true,
|
@@ -64,19 +67,24 @@ module Netzke
|
|
64
67
|
end
|
65
68
|
|
66
69
|
def property_widgets
|
67
|
-
[
|
70
|
+
res = []
|
71
|
+
res << {
|
68
72
|
:name => 'columns',
|
69
73
|
:widget_class_name => "FieldsConfigurator",
|
70
74
|
:ext_config => {:title => false},
|
71
75
|
:active => true,
|
72
76
|
:layout => NetzkeLayout.by_widget(id_name)
|
73
|
-
}
|
77
|
+
} if config[:persistent_layout]
|
78
|
+
|
79
|
+
res << {
|
74
80
|
:name => 'general',
|
75
81
|
:widget_class_name => "PreferenceGrid",
|
76
82
|
:host_widget_name => id_name,
|
77
83
|
:default_properties => available_permissions.map{ |k| {:name => "permissions.#{k}", :value => @permissions[k.to_sym]}},
|
78
84
|
:ext_config => {:title => false}
|
79
|
-
}
|
85
|
+
}
|
86
|
+
|
87
|
+
res
|
80
88
|
end
|
81
89
|
|
82
90
|
def properties__general__load_source(params = {})
|
@@ -98,9 +106,9 @@ module Netzke
|
|
98
106
|
if config[:persistent_layout] && layout_manager_class && column_manager_class
|
99
107
|
layout = layout_manager_class.by_widget(id_name)
|
100
108
|
layout ||= column_manager_class.create_layout_for_widget(self)
|
101
|
-
layout.
|
109
|
+
layout.items_arry
|
102
110
|
else
|
103
|
-
|
111
|
+
default_db_fields
|
104
112
|
end
|
105
113
|
end
|
106
114
|
|
@@ -110,13 +118,13 @@ module Netzke
|
|
110
118
|
|
111
119
|
def actions
|
112
120
|
[{
|
113
|
-
:text => 'Add', :
|
121
|
+
:text => 'Add', :handler_name => 'add', :disabled => !@permissions[:create], :id => 'add'
|
114
122
|
},{
|
115
|
-
:text => 'Edit', :
|
123
|
+
:text => 'Edit', :handler_name => 'edit', :disabled => !@permissions[:update], :id => 'edit'
|
116
124
|
},{
|
117
|
-
:text => 'Delete', :
|
125
|
+
:text => 'Delete', :handler_name => 'delete', :disabled => !@permissions[:delete], :id => 'delete'
|
118
126
|
},{
|
119
|
-
:text => 'Apply', :
|
127
|
+
:text => 'Apply', :handler_name => 'submit', :disabled => !@permissions[:update] && !@permissions[:create], :id => 'apply'
|
120
128
|
}]
|
121
129
|
end
|
122
130
|
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module Netzke
|
2
|
+
module GridPanelExtras
|
3
|
+
module Interface
|
4
|
+
def post_data(params)
|
5
|
+
success = true
|
6
|
+
mod_record_ids = {}
|
7
|
+
[:create, :update].each do |operation|
|
8
|
+
data = JSON.parse(params.delete("#{operation}d_records".to_sym)) if params["#{operation}d_records".to_sym]
|
9
|
+
if !data.nil? && !data.empty? # data may be nil for one of the operations
|
10
|
+
mod_record_ids[operation] = process_data(data, operation)
|
11
|
+
end
|
12
|
+
break if !success
|
13
|
+
end
|
14
|
+
{:success => success, :flash => @flash, :mod_record_ids => mod_record_ids}
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_data(params = {})
|
18
|
+
if @permissions[:read]
|
19
|
+
records = get_records(params)
|
20
|
+
{:data => records, :total => records.total_records}
|
21
|
+
else
|
22
|
+
flash :error => "You don't have permissions to read data"
|
23
|
+
{:success => false, :flash => @flash}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_data(params = {})
|
28
|
+
if @permissions[:delete]
|
29
|
+
record_ids = JSON.parse(params.delete(:records))
|
30
|
+
klass = config[:data_class_name].constantize
|
31
|
+
klass.delete(record_ids)
|
32
|
+
flash :notice => "Deleted #{record_ids.size} record(s)"
|
33
|
+
success = true
|
34
|
+
else
|
35
|
+
flash :error => "You don't have permissions to delete data"
|
36
|
+
success = false
|
37
|
+
end
|
38
|
+
{:success => success, :flash => @flash}
|
39
|
+
end
|
40
|
+
|
41
|
+
def resize_column(params)
|
42
|
+
raise "Called interface_resize_column while not configured to do so" unless config[:ext_config][:enable_column_resize]
|
43
|
+
if config[:persistent_layout] && layout_manager_class
|
44
|
+
l_item = layout_manager_class.by_widget(id_name).items[params[:index].to_i]
|
45
|
+
l_item.width = params[:size]
|
46
|
+
l_item.save!
|
47
|
+
end
|
48
|
+
{}
|
49
|
+
end
|
50
|
+
|
51
|
+
def move_column(params)
|
52
|
+
raise "Called interface_move_column while not configured to do so" unless config[:ext_config][:enable_column_move]
|
53
|
+
if config[:persistent_layout] && layout_manager_class
|
54
|
+
layout_manager_class.by_widget(id_name).move_item(params[:old_index].to_i, params[:new_index].to_i)
|
55
|
+
end
|
56
|
+
{}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Return the choices for the column
|
60
|
+
def get_cb_choices(params)
|
61
|
+
column = params[:column]
|
62
|
+
query = params[:query]
|
63
|
+
|
64
|
+
{:data => config[:data_class_name].constantize.choices_for(column, query).map{|s| [s]}}
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
# operation => :update || :create
|
71
|
+
def process_data(data, operation)
|
72
|
+
success = true
|
73
|
+
mod_record_ids = []
|
74
|
+
if @permissions[operation]
|
75
|
+
klass = config[:data_class_name].constantize
|
76
|
+
modified_records = 0
|
77
|
+
data.each do |record_hash|
|
78
|
+
id = record_hash.delete('id')
|
79
|
+
record = operation == :create ? klass.new : klass.find(id)
|
80
|
+
success = true
|
81
|
+
|
82
|
+
# process all attirubutes for the same record (OPTIMIZE: we can use update_attributes separately for regular attributes to speed things up)
|
83
|
+
record_hash.each_pair do |k,v|
|
84
|
+
begin
|
85
|
+
record.send("#{k}=",v)
|
86
|
+
rescue ArgumentError => exc
|
87
|
+
flash :error => exc.message
|
88
|
+
success = false
|
89
|
+
break
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# try to save
|
94
|
+
# modified_records += 1 if success && record.save
|
95
|
+
mod_record_ids << id if success && record.save
|
96
|
+
|
97
|
+
# flash eventual errors
|
98
|
+
if !record.errors.empty?
|
99
|
+
success = false
|
100
|
+
record.errors.each_full do |msg|
|
101
|
+
flash :error => msg
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
# flash :notice => "#{operation.to_s.capitalize}d #{modified_records} record(s)"
|
106
|
+
else
|
107
|
+
success = false
|
108
|
+
flash :error => "You don't have permissions to #{operation} data"
|
109
|
+
end
|
110
|
+
mod_record_ids
|
111
|
+
end
|
112
|
+
|
113
|
+
# get records
|
114
|
+
def get_records(params)
|
115
|
+
search_params = normalize_params(params) # make params coming from the browser understandable by searchlogic
|
116
|
+
search_params[:conditions].recursive_merge!(config[:conditions] || {}) # merge with conditions coming from the config
|
117
|
+
|
118
|
+
raise ArgumentError, "No data_class_name specified for widget '#{config[:name]}'" if !config[:data_class_name]
|
119
|
+
records = config[:data_class_name].constantize.all(search_params.clone) # clone needed as searchlogic removes :conditions key from the hash
|
120
|
+
# output_array = []
|
121
|
+
columns = get_columns
|
122
|
+
output_array = records.map{|r| r.to_array(columns)}
|
123
|
+
|
124
|
+
# records.each do |r|
|
125
|
+
# r_array = []
|
126
|
+
# self.get_columns.each do |column|
|
127
|
+
# r_array << r.send(column[:name])
|
128
|
+
# end
|
129
|
+
# output_array << r_array
|
130
|
+
# output_array << r.to_array(columns)
|
131
|
+
# end
|
132
|
+
|
133
|
+
# add total_entries accessor to the result
|
134
|
+
class << output_array
|
135
|
+
attr :total_records, true
|
136
|
+
end
|
137
|
+
total_records_count = config[:data_class_name].constantize.count(search_params)
|
138
|
+
output_array.total_records = total_records_count
|
139
|
+
|
140
|
+
output_array
|
141
|
+
end
|
142
|
+
|
143
|
+
def convert_filters(column_filter)
|
144
|
+
res = {}
|
145
|
+
column_filter.each_pair do |k,v|
|
146
|
+
field = v["field"]
|
147
|
+
case v["data"]["type"]
|
148
|
+
when "string"
|
149
|
+
field << "_contains"
|
150
|
+
when "numeric"
|
151
|
+
field << "_#{v["data"]["comparison"]}"
|
152
|
+
end
|
153
|
+
value = v["data"]["value"]
|
154
|
+
res.merge!({field => value})
|
155
|
+
end
|
156
|
+
res
|
157
|
+
end
|
158
|
+
|
159
|
+
# make params understandable to searchlogic
|
160
|
+
def normalize_params(params)
|
161
|
+
# filters
|
162
|
+
conditions = params[:filter] && convert_filters(params[:filter])
|
163
|
+
|
164
|
+
normalized_conditions = {}
|
165
|
+
conditions && conditions.each_pair do |k, v|
|
166
|
+
assoc, method = k.split('__')
|
167
|
+
normalized_conditions.merge!(method.nil? ? {assoc => v} : {assoc => {method => v}})
|
168
|
+
end
|
169
|
+
|
170
|
+
# sorting
|
171
|
+
order_by = if params[:sort]
|
172
|
+
assoc, method = params[:sort].split('__')
|
173
|
+
method.nil? ? assoc : {assoc => method}
|
174
|
+
end
|
175
|
+
|
176
|
+
page = params[:start].to_i/params[:limit].to_i + 1 if params[:limit]
|
177
|
+
{:per_page => params[:limit], :page => page, :order_by => order_by, :order_as => params[:dir], :conditions => normalized_conditions}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,322 @@
|
|
1
|
+
module Netzke
|
2
|
+
module GridPanelExtras
|
3
|
+
module JsBuilder
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
def js_config
|
9
|
+
res = super
|
10
|
+
# we pass column config at the time of instantiating the JS class
|
11
|
+
res.merge!(:columns => get_columns || config[:columns]) # first try to get columns from DB, then from config
|
12
|
+
res.merge!(:data_class_name => config[:data_class_name])
|
13
|
+
res
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
def js_base_class
|
19
|
+
'Ext.grid.EditorGridPanel'
|
20
|
+
end
|
21
|
+
|
22
|
+
def js_bbar
|
23
|
+
<<-JS.l
|
24
|
+
(config.rowsPerPage) ? new Ext.PagingToolbar({
|
25
|
+
pageSize:config.rowsPerPage,
|
26
|
+
items:config.actions,
|
27
|
+
store:ds,
|
28
|
+
emptyMsg:'Empty'}) : config.actions
|
29
|
+
JS
|
30
|
+
end
|
31
|
+
|
32
|
+
def js_default_config
|
33
|
+
super.merge({
|
34
|
+
:store => "ds".l,
|
35
|
+
:cm => "cm".l,
|
36
|
+
:sel_model => "new Ext.grid.RowSelectionModel()".l,
|
37
|
+
:auto_scroll => true,
|
38
|
+
:click_to_edit => 2,
|
39
|
+
:track_mouse_over => true,
|
40
|
+
# :bbar => "config.actions".l,
|
41
|
+
:bbar => js_bbar,
|
42
|
+
:plugins => "plugins".l,
|
43
|
+
|
44
|
+
#custom configs
|
45
|
+
:auto_load_data => true
|
46
|
+
})
|
47
|
+
end
|
48
|
+
|
49
|
+
def js_before_constructor
|
50
|
+
<<-JS
|
51
|
+
var plugins = [];
|
52
|
+
if (!config.columns) this.feedback('No columns defined for grid '+config.id);
|
53
|
+
this.recordConfig = [];
|
54
|
+
Ext.each(config.columns, function(column){this.recordConfig.push({name:column.name})}, this);
|
55
|
+
this.Row = Ext.data.Record.create(this.recordConfig);
|
56
|
+
|
57
|
+
var ds = new Ext.data.Store({
|
58
|
+
proxy: this.proxy = new Ext.data.HttpProxy({url:config.interface.getData}),
|
59
|
+
reader: new Ext.data.ArrayReader({root: "data", totalProperty: "total", successProperty: "succes", id:0}, this.Row),
|
60
|
+
remoteSort: true,
|
61
|
+
listeners:{'loadexception':{
|
62
|
+
fn:this.loadExceptionHandler,
|
63
|
+
scope:this
|
64
|
+
}}
|
65
|
+
});
|
66
|
+
|
67
|
+
this.cmConfig = [];
|
68
|
+
Ext.each(config.columns, function(c){
|
69
|
+
var extConfig;
|
70
|
+
try{
|
71
|
+
extConfig = Ext.decode(c.extConfig);
|
72
|
+
}
|
73
|
+
catch(err){
|
74
|
+
extConfig = {}
|
75
|
+
}
|
76
|
+
delete(c.extConfig);
|
77
|
+
|
78
|
+
if (c.editor == 'checkbox') {
|
79
|
+
var plugin = new Ext.grid.CheckColumn(Ext.apply({
|
80
|
+
header : c.label || c.name,
|
81
|
+
dataIndex : c.name,
|
82
|
+
disabled : c.readOnly,
|
83
|
+
hidden : c.hidden,
|
84
|
+
width : c.width
|
85
|
+
}, extConfig));
|
86
|
+
|
87
|
+
plugins.push(plugin);
|
88
|
+
this.cmConfig.push(plugin);
|
89
|
+
|
90
|
+
} else {
|
91
|
+
var editor = (c.readOnly || !config.permissions.update) ? null : Ext.netzke.editors[c.editor](c, config);
|
92
|
+
var renderer = Ext.netzke.renderer(c.renderer);
|
93
|
+
|
94
|
+
this.cmConfig.push(Ext.apply({
|
95
|
+
header : c.label || c.name,
|
96
|
+
dataIndex : c.name,
|
97
|
+
hidden : c.hidden,
|
98
|
+
width : c.width,
|
99
|
+
editor : editor,
|
100
|
+
renderer : renderer,
|
101
|
+
sortable : true
|
102
|
+
}, extConfig))
|
103
|
+
}
|
104
|
+
|
105
|
+
}, this);
|
106
|
+
|
107
|
+
var cm = new Ext.grid.ColumnModel(this.cmConfig);
|
108
|
+
|
109
|
+
this.addEvents("refresh");
|
110
|
+
|
111
|
+
// Filters
|
112
|
+
if (config.enableColumnFilters) {
|
113
|
+
var filters = []
|
114
|
+
Ext.each(config.columns, function(c){
|
115
|
+
filters.push({type:Ext.netzke.filterMap[c.editor], dataIndex:c.name})
|
116
|
+
})
|
117
|
+
var gridFilters = new Ext.grid.GridFilters({filters:filters});
|
118
|
+
plugins.push(gridFilters);
|
119
|
+
}
|
120
|
+
|
121
|
+
JS
|
122
|
+
end
|
123
|
+
|
124
|
+
def js_listeners
|
125
|
+
super.merge({
|
126
|
+
:columnresize => {:fn => "this.onColumnResize".l, :scope => this},
|
127
|
+
:columnmove => {:fn => "this.onColumnMove".l, :scope => this}
|
128
|
+
})
|
129
|
+
end
|
130
|
+
|
131
|
+
def js_extend_properties
|
132
|
+
{
|
133
|
+
:on_widget_load => <<-JS.l,
|
134
|
+
function(){
|
135
|
+
// auto-load
|
136
|
+
if (this.initialConfig.autoLoadData) {
|
137
|
+
// if we have a paging toolbar, load the first page, otherwise
|
138
|
+
if (this.getBottomToolbar().changePage) this.getBottomToolbar().changePage(0); else this.store.load();
|
139
|
+
}
|
140
|
+
}
|
141
|
+
JS
|
142
|
+
|
143
|
+
:load_exception_handler => <<-JS.l,
|
144
|
+
function(proxy, options, response, error){
|
145
|
+
if (response.status == 200 && (responseObject = Ext.decode(response.responseText)) && responseObject.flash){
|
146
|
+
this.feedback(responseObject.flash)
|
147
|
+
} else {
|
148
|
+
if (error){
|
149
|
+
this.feedback(error.message);
|
150
|
+
} else {
|
151
|
+
this.feedback(response.statusText)
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
JS
|
156
|
+
|
157
|
+
:add => <<-JS.l,
|
158
|
+
function(){
|
159
|
+
var rowConfig = {};
|
160
|
+
Ext.each(this.initialConfig.columns, function(c){
|
161
|
+
rowConfig[c.name] = c.defaultValue || ''; // FIXME: if the user is happy with all the defaults, the record won't be 'dirty'
|
162
|
+
}, this);
|
163
|
+
|
164
|
+
var r = new this.Row(rowConfig); // TODO: add default values
|
165
|
+
r.new = true; // to distinguish new records
|
166
|
+
r.set('id', r.id); // otherwise later r.get('id') returns empty string
|
167
|
+
this.stopEditing();
|
168
|
+
this.store.add(r);
|
169
|
+
// this.store.newRecords = this.store.newRecords || []
|
170
|
+
// this.store.newRecords.push(r);
|
171
|
+
this.tryStartEditing(this.store.indexOf(r));
|
172
|
+
}
|
173
|
+
JS
|
174
|
+
|
175
|
+
:edit => <<-JS.l,
|
176
|
+
function(){
|
177
|
+
var row = this.getSelectionModel().getSelected();
|
178
|
+
if (row){
|
179
|
+
this.tryStartEditing(this.store.indexOf(row))
|
180
|
+
}
|
181
|
+
}
|
182
|
+
JS
|
183
|
+
|
184
|
+
# try editing the first editable (not hidden, not read-only) sell
|
185
|
+
:try_start_editing => <<-JS.l,
|
186
|
+
function(row){
|
187
|
+
if (row == null) return;
|
188
|
+
var editableColumns = this.getColumnModel().getColumnsBy(function(columnConfig, index){
|
189
|
+
return !columnConfig.hidden && !!columnConfig.editor;
|
190
|
+
});
|
191
|
+
// console.info(editableColumns);
|
192
|
+
var firstEditableColumn = editableColumns[0];
|
193
|
+
if (firstEditableColumn){
|
194
|
+
this.startEditing(row, firstEditableColumn.id);
|
195
|
+
}
|
196
|
+
}
|
197
|
+
JS
|
198
|
+
|
199
|
+
:delete => <<-JS.l,
|
200
|
+
function() {
|
201
|
+
if (this.getSelectionModel().hasSelection()){
|
202
|
+
Ext.Msg.confirm('Confirm', 'Are you sure?', function(btn){
|
203
|
+
if (btn == 'yes') {
|
204
|
+
var records = []
|
205
|
+
this.getSelectionModel().each(function(r){
|
206
|
+
records.push(r.get('id'));
|
207
|
+
}, this);
|
208
|
+
Ext.Ajax.request({
|
209
|
+
url: this.initialConfig.interface.deleteData,
|
210
|
+
params: {records: Ext.encode(records)},
|
211
|
+
success:function(r){
|
212
|
+
var m = Ext.decode(r.responseText);
|
213
|
+
this.store.reload();
|
214
|
+
this.feedback(m.flash);
|
215
|
+
},
|
216
|
+
scope:this
|
217
|
+
});
|
218
|
+
}
|
219
|
+
}, this);
|
220
|
+
}
|
221
|
+
}
|
222
|
+
JS
|
223
|
+
:submit => <<-JS.l,
|
224
|
+
function(){
|
225
|
+
|
226
|
+
var newRecords = [];
|
227
|
+
// if (this.store.newRecords){
|
228
|
+
// Ext.each(this.store.newRecords, function(r){
|
229
|
+
// newRecords.push(r.getChanges())
|
230
|
+
// }, this);
|
231
|
+
// // delete this.store.newRecords;
|
232
|
+
// }
|
233
|
+
|
234
|
+
var updatedRecords = [];
|
235
|
+
|
236
|
+
Ext.each(this.store.getModifiedRecords(),
|
237
|
+
function(r) {
|
238
|
+
if (r.new) {
|
239
|
+
newRecords.push(Ext.apply(r.getChanges(), {id:r.get('id')}));
|
240
|
+
} else {
|
241
|
+
updatedRecords.push(Ext.apply(r.getChanges(), {id:r.get('id')}));
|
242
|
+
}
|
243
|
+
},
|
244
|
+
this);
|
245
|
+
|
246
|
+
if (newRecords.length > 0 || updatedRecords.length > 0) {
|
247
|
+
Ext.Ajax.request({
|
248
|
+
url:this.initialConfig.interface.postData,
|
249
|
+
params: {
|
250
|
+
updated_records: Ext.encode(updatedRecords),
|
251
|
+
created_records: Ext.encode(newRecords),
|
252
|
+
filters: this.store.baseParams.filters
|
253
|
+
},
|
254
|
+
success:function(response){
|
255
|
+
var m = Ext.decode(response.responseText);
|
256
|
+
if (m.success) {
|
257
|
+
// commit those rows that have successfully been updated/created
|
258
|
+
var modRecords = [].concat(this.store.getModifiedRecords()) // there must be a better way to clone an array...
|
259
|
+
Ext.each(modRecords, function(r){
|
260
|
+
var idsToSearch = r.new ? m.modRecordIds.create : m.modRecordIds.update
|
261
|
+
if (idsToSearch.indexOf(r.id) >= 0) r.commit();
|
262
|
+
})
|
263
|
+
|
264
|
+
// reload the grid only when there were no errors
|
265
|
+
// (we need to reload because of filtering, sorting, etc)
|
266
|
+
if (this.store.getModifiedRecords().length == 0){
|
267
|
+
this.store.reload();
|
268
|
+
}
|
269
|
+
|
270
|
+
this.feedback(m.flash);
|
271
|
+
} else {
|
272
|
+
this.feedback(m.flash);
|
273
|
+
}
|
274
|
+
},
|
275
|
+
failure:function(response){
|
276
|
+
this.feedback('Bad response from server');
|
277
|
+
},
|
278
|
+
scope:this
|
279
|
+
});
|
280
|
+
}
|
281
|
+
|
282
|
+
}
|
283
|
+
JS
|
284
|
+
|
285
|
+
:refresh_click => <<-JS.l,
|
286
|
+
function() {
|
287
|
+
// console.info(this);
|
288
|
+
// if (this.fireEvent('refresh', this) !== false) this.loadWithFeedback();
|
289
|
+
if (this.fireEvent('refresh', this) !== false) this.store.reload();
|
290
|
+
}
|
291
|
+
JS
|
292
|
+
|
293
|
+
:on_column_resize => <<-JS.l,
|
294
|
+
function(index, size){
|
295
|
+
Ext.Ajax.request({
|
296
|
+
url:this.initialConfig.interface.resizeColumn,
|
297
|
+
params:{
|
298
|
+
index:index,
|
299
|
+
size:size
|
300
|
+
}
|
301
|
+
})
|
302
|
+
}
|
303
|
+
JS
|
304
|
+
|
305
|
+
:on_column_move => <<-JS.l
|
306
|
+
function(oldIndex, newIndex){
|
307
|
+
Ext.Ajax.request({
|
308
|
+
url:this.initialConfig.interface.moveColumn,
|
309
|
+
params:{
|
310
|
+
old_index:oldIndex,
|
311
|
+
new_index:newIndex
|
312
|
+
}
|
313
|
+
})
|
314
|
+
}
|
315
|
+
JS
|
316
|
+
|
317
|
+
}
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|