skozlov-netzke_core 0.1.0
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 +1 -0
- data/LICENSE +20 -0
- data/Manifest +64 -0
- data/README.mdown +18 -0
- data/Rakefile +11 -0
- data/generators/netzke_basepack/USAGE +8 -0
- data/generators/netzke_basepack/netzke_basepack_generator.rb +8 -0
- data/generators/netzke_basepack/netzke_grid_generator.rb +7 -0
- data/generators/netzke_basepack/templates/create_netzke_grid_columns.rb +21 -0
- data/init.rb +2 -0
- data/install.rb +1 -0
- data/javascripts/basepack.js +41 -0
- data/lib/app/models/netzke_grid_column.rb +23 -0
- data/lib/netzke/accordion.rb +11 -0
- data/lib/netzke/ar_ext.rb +163 -0
- data/lib/netzke/column.rb +43 -0
- data/lib/netzke/container.rb +81 -0
- data/lib/netzke/grid.rb +132 -0
- data/lib/netzke/grid_interface.rb +132 -0
- data/lib/netzke/grid_js_builder.rb +249 -0
- data/lib/netzke/preference_grid.rb +43 -0
- data/lib/netzke/properties_tool.rb +66 -0
- data/lib/netzke/property_grid.rb +60 -0
- data/lib/netzke_basepack.rb +14 -0
- data/netzke_core.gemspec +38 -0
- data/tasks/netzke_basepack_tasks.rake +4 -0
- data/test/app_root/app/controllers/application.rb +2 -0
- data/test/app_root/app/models/book.rb +9 -0
- data/test/app_root/app/models/category.rb +2 -0
- data/test/app_root/app/models/city.rb +3 -0
- data/test/app_root/app/models/continent.rb +2 -0
- data/test/app_root/app/models/country.rb +3 -0
- data/test/app_root/app/models/genre.rb +3 -0
- data/test/app_root/config/boot.rb +114 -0
- data/test/app_root/config/database.yml +21 -0
- data/test/app_root/config/environment.rb +13 -0
- data/test/app_root/config/environments/in_memory.rb +0 -0
- data/test/app_root/config/environments/mysql.rb +0 -0
- data/test/app_root/config/environments/postgresql.rb +0 -0
- data/test/app_root/config/environments/sqlite.rb +0 -0
- data/test/app_root/config/environments/sqlite3.rb +0 -0
- data/test/app_root/config/routes.rb +4 -0
- data/test/app_root/db/migrate/20081222033343_create_books.rb +15 -0
- data/test/app_root/db/migrate/20081222033440_create_genres.rb +14 -0
- data/test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb +18 -0
- data/test/app_root/db/migrate/20081223024935_create_categories.rb +13 -0
- data/test/app_root/db/migrate/20081223025635_create_countries.rb +14 -0
- data/test/app_root/db/migrate/20081223025653_create_continents.rb +13 -0
- data/test/app_root/db/migrate/20081223025732_create_cities.rb +15 -0
- data/test/app_root/script/console +7 -0
- data/test/ar_ext_test.rb +39 -0
- data/test/column_test.rb +27 -0
- data/test/console_with_fixtures.rb +4 -0
- data/test/fixtures/books.yml +9 -0
- data/test/fixtures/categories.yml +7 -0
- data/test/fixtures/cities.yml +21 -0
- data/test/fixtures/continents.yml +7 -0
- data/test/fixtures/countries.yml +9 -0
- data/test/fixtures/genres.yml +9 -0
- data/test/grid_test.rb +43 -0
- data/test/netzke_basepack_test.rb +8 -0
- data/test/schema.rb +10 -0
- data/test/test_helper.rb +20 -0
- data/uninstall.rb +1 -0
- metadata +159 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
module Netzke
|
2
|
+
#
|
3
|
+
# Base class for Accordion and TabPanel widgets, it shouldn't be used as a stand-alone class.
|
4
|
+
#
|
5
|
+
class Container < Base
|
6
|
+
def initialize(*args)
|
7
|
+
super
|
8
|
+
for item in initial_items do
|
9
|
+
add_aggregatee item
|
10
|
+
items << item.keys.first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initial_dependencies
|
15
|
+
dep = super
|
16
|
+
for item in items
|
17
|
+
candidate_dependency = aggregatees[item][:widget_class_name]
|
18
|
+
dep << candidate_dependency unless dep.include?(candidate_dependency)
|
19
|
+
end
|
20
|
+
dep
|
21
|
+
end
|
22
|
+
|
23
|
+
def js_before_constructor
|
24
|
+
js_widget_items
|
25
|
+
end
|
26
|
+
|
27
|
+
def items
|
28
|
+
@items ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
def initial_items
|
32
|
+
config[:items] || []
|
33
|
+
end
|
34
|
+
|
35
|
+
def js_widget_items
|
36
|
+
res = ""
|
37
|
+
item_aggregatees.each_pair do |k,v|
|
38
|
+
next if v[:late_aggregation]
|
39
|
+
res << <<-JS
|
40
|
+
var #{k.to_js} = new Ext.componentCache['#{v[:widget_class_name]}'](config.#{k.to_js}Config);
|
41
|
+
JS
|
42
|
+
end
|
43
|
+
res
|
44
|
+
end
|
45
|
+
|
46
|
+
def js_items
|
47
|
+
items.inject([]) do |a,i|
|
48
|
+
a << {
|
49
|
+
:title => i.to_s.humanize,
|
50
|
+
:layout => 'fit',
|
51
|
+
:id => i.to_s,
|
52
|
+
# :id => "#{config[:name]}_#{i.to_s}",
|
53
|
+
:items => ([i.to_s.to_js.l] if !aggregatees[i][:late_aggregation]),
|
54
|
+
# these listeners will be different for tab_panel and accordion
|
55
|
+
:collapsed => !aggregatees[i][:active],
|
56
|
+
:listeners => {
|
57
|
+
# :activate => {:fn => "function(p){this.feedback(p.id)}".l, :scope => this},
|
58
|
+
:expand => {:fn => "this.loadItemWidget".l, :scope => this}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def js_extend_properties
|
65
|
+
{
|
66
|
+
# loads widget into the panel if it's not loaded yet
|
67
|
+
:load_item_widget => <<-JS.l,
|
68
|
+
function(panel) {
|
69
|
+
if (!panel.getWidget()) panel.loadWidget(this.id + "__" + panel.id + "__get_widget");
|
70
|
+
// if (!this.getWidgetByPanel(panel)) this.loadWidget(panel, this.initialConfig[panel.id+'Config'].interface.getWidget);
|
71
|
+
}
|
72
|
+
JS
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
def item_aggregatees
|
78
|
+
aggregatees.delete_if{|k,v| !@items.include?(k)}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/netzke/grid.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'searchlogic'
|
2
|
+
module Netzke
|
3
|
+
#
|
4
|
+
# Functionality:
|
5
|
+
# * data operations - get, post, delete, create
|
6
|
+
# * column resize and move
|
7
|
+
# * permissions
|
8
|
+
# * sorting - TODO
|
9
|
+
# * pagination
|
10
|
+
# * validation - TODO
|
11
|
+
# * properties and column configuration
|
12
|
+
#
|
13
|
+
class Grid < Base
|
14
|
+
include GridJsBuilder
|
15
|
+
include GridInterface
|
16
|
+
# define connection points between client side and server side of Grid. See implementation of equally named methods in the GridInterface module.
|
17
|
+
interface :get_data, :post_data, :delete_data, :resize_column, :move_column, :get_cb_choices
|
18
|
+
|
19
|
+
def initial_config
|
20
|
+
{
|
21
|
+
:ext_config => {:properties => true},
|
22
|
+
:layout_manager => "NetzkeLayout"
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def property_widgets
|
27
|
+
[{
|
28
|
+
:columns => {
|
29
|
+
:widget_class_name => "Grid",
|
30
|
+
:data_class_name => column_manager_class_name,
|
31
|
+
:ext_config => {:title => false, :properties => false},
|
32
|
+
:active => true
|
33
|
+
}
|
34
|
+
},{
|
35
|
+
:general => {
|
36
|
+
:widget_class_name => "PreferenceGrid",
|
37
|
+
:host_widget_name => @id_name,
|
38
|
+
:default_properties => available_permissions.map{ |k| {:name => "permissions.#{k}", :value => @permissions[k.to_sym]}},
|
39
|
+
:ext_config => {:title => false}
|
40
|
+
}
|
41
|
+
}]
|
42
|
+
end
|
43
|
+
|
44
|
+
## Data for properties grid
|
45
|
+
def properties__columns__get_data(params = {})
|
46
|
+
columns_widget = aggregatee_instance(:properties__columns)
|
47
|
+
|
48
|
+
layout_id = layout_manager_class.by_widget(id_name).id
|
49
|
+
columns_widget.interface_get_data(params.merge(:filters => {:layout_id => layout_id}))
|
50
|
+
end
|
51
|
+
|
52
|
+
def properties__general__load_source(params = {})
|
53
|
+
w = aggregatee_instance(:properties__general)
|
54
|
+
w.interface_load_source(params)
|
55
|
+
end
|
56
|
+
|
57
|
+
# we pass column config at the time of instantiating the JS class
|
58
|
+
def js_config
|
59
|
+
res = super
|
60
|
+
res.merge!(:columns => get_columns || config[:columns]) # first try to get columns from DB, then from config
|
61
|
+
res.merge!(:data_class_name => config[:data_class_name])
|
62
|
+
res
|
63
|
+
end
|
64
|
+
|
65
|
+
def js_listeners
|
66
|
+
super.merge({
|
67
|
+
:columnresize => (config[:column_resize] ? {:fn => "this.onColumnResize".l, :scope => this} : nil),
|
68
|
+
:columnmove => (config[:column_move] ? {:fn => "this.onColumnMove".l, :scope => this} : nil)
|
69
|
+
})
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def layout_manager_class
|
76
|
+
config[:layout_manager] && config[:layout_manager].constantize
|
77
|
+
end
|
78
|
+
|
79
|
+
def column_manager_class_name
|
80
|
+
"NetzkeGridColumn"
|
81
|
+
end
|
82
|
+
|
83
|
+
def column_manager_class
|
84
|
+
column_manager_class_name.constantize
|
85
|
+
rescue NameError
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
|
89
|
+
def available_permissions
|
90
|
+
%w(read update create delete)
|
91
|
+
end
|
92
|
+
|
93
|
+
public
|
94
|
+
|
95
|
+
# get columns from layout manager
|
96
|
+
def get_columns
|
97
|
+
if layout_manager_class
|
98
|
+
layout = layout_manager_class.by_widget(id_name)
|
99
|
+
layout ||= column_manager_class.create_layout_for_widget(self)
|
100
|
+
layout.items_hash # TODO: bad name!
|
101
|
+
else
|
102
|
+
Netzke::Column.default_columns_for_widget(self)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def tools
|
107
|
+
[{:id => 'refresh', :on => {:click => 'refreshClick'}}]
|
108
|
+
end
|
109
|
+
|
110
|
+
def actions
|
111
|
+
[{
|
112
|
+
:text => 'Add', :handler => 'add', :disabled => @pref['permissions.create'] == false
|
113
|
+
},{
|
114
|
+
:text => 'Edit', :handler => 'edit', :disabled => @pref['permissions.update'] == false
|
115
|
+
},{
|
116
|
+
:text => 'Delete', :handler => 'delete', :disabled => @pref['permissions.delete'] == false
|
117
|
+
},{
|
118
|
+
:text => 'Apply', :handler => 'submit', :disabled => @pref['permissions.update'] == false && @pref['permissions.create'] == false
|
119
|
+
}]
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
# Uncomment to enable a menu duplicating the actions
|
125
|
+
# def js_menus
|
126
|
+
# [{:text => "config.dataClassName".l, :menu => "config.actions".l}]
|
127
|
+
# end
|
128
|
+
|
129
|
+
# include ColumnOperations
|
130
|
+
include PropertiesTool # it will load aggregation with name :properties into a modal window
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Netzke::GridInterface
|
2
|
+
def post_data(params)
|
3
|
+
[:create, :update].each do |operation|
|
4
|
+
data = JSON.parse(params.delete("#{operation}d_records".to_sym)) if params["#{operation}d_records".to_sym]
|
5
|
+
process_data(data, operation) if !data.nil?
|
6
|
+
end
|
7
|
+
{:success => true, :flash => @flash}
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_data(params = {})
|
11
|
+
if @permissions[:read]
|
12
|
+
records = get_records(params)
|
13
|
+
{:data => records, :total => records.total_records}
|
14
|
+
else
|
15
|
+
flash :error => "You don't have permissions to read data"
|
16
|
+
{:success => false, :flash => @flash}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete_data(params = {})
|
21
|
+
if @permissions[:delete]
|
22
|
+
record_ids = JSON.parse(params.delete(:records))
|
23
|
+
klass = config[:data_class_name].constantize
|
24
|
+
klass.delete(record_ids)
|
25
|
+
flash :notice => "Deleted #{record_ids.size} record(s)"
|
26
|
+
success = true
|
27
|
+
else
|
28
|
+
flash :error => "You don't have permissions to delete data"
|
29
|
+
success = false
|
30
|
+
end
|
31
|
+
{:success => success, :flash => @flash}
|
32
|
+
end
|
33
|
+
|
34
|
+
def resize_column(params)
|
35
|
+
raise "Called interface_resize_column while not configured to do so" unless config[:column_resize]
|
36
|
+
l_item = layout_manager_class.by_widget(id_name).layout_items[params[:index].to_i]
|
37
|
+
l_item.width = params[:size]
|
38
|
+
l_item.save!
|
39
|
+
{}
|
40
|
+
end
|
41
|
+
|
42
|
+
def move_column(params)
|
43
|
+
raise "Called interface_move_column while not configured to do so" unless config[:column_move]
|
44
|
+
layout_manager_class.by_widget(id_name).move_item(params[:old_index].to_i, params[:new_index].to_i)
|
45
|
+
{}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return the choices for the column
|
49
|
+
def get_cb_choices(params)
|
50
|
+
column = params[:column]
|
51
|
+
query = params[:query]
|
52
|
+
|
53
|
+
{:data => config[:data_class_name].constantize.choices_for(column, query).map{|s| [s]}}
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
protected
|
58
|
+
#
|
59
|
+
# operation => :update || :create
|
60
|
+
#
|
61
|
+
def process_data(data, operation)
|
62
|
+
if @permissions[operation]
|
63
|
+
klass = config[:data_class_name].constantize
|
64
|
+
modified_records = 0
|
65
|
+
data.each do |record_hash|
|
66
|
+
record = operation == :create ? klass.create : klass.find(record_hash.delete('id'))
|
67
|
+
logger.debug { "!!! record: #{record.inspect}" }
|
68
|
+
success = true
|
69
|
+
exception = nil
|
70
|
+
|
71
|
+
# process all attirubutes for the same record (OPTIMIZE: we can use update_attributes separately for regular attributes to speed things up)
|
72
|
+
record_hash.each_pair do |k,v|
|
73
|
+
begin
|
74
|
+
record.send("#{k}=",v)
|
75
|
+
rescue ArgumentError => exc
|
76
|
+
flash :error => exc.message
|
77
|
+
success = false
|
78
|
+
break
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# try to save
|
83
|
+
modified_records += 1 if success && record.save
|
84
|
+
|
85
|
+
# flash eventual errors
|
86
|
+
record.errors.each_full do |msg|
|
87
|
+
flash :error => msg
|
88
|
+
end
|
89
|
+
|
90
|
+
flash :notice => "#{operation.to_s.capitalize}d #{modified_records} records"
|
91
|
+
end
|
92
|
+
else
|
93
|
+
flash :error => "You don't have permissions to #{operation} data"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# get records
|
98
|
+
def get_records(params)
|
99
|
+
conditions = normalize_params(params)
|
100
|
+
raise ArgumentError, "No data_class_name specified for widget '#{config[:name]}'" if !config[:data_class_name]
|
101
|
+
records = config[:data_class_name].constantize.all(conditions)
|
102
|
+
output_array = []
|
103
|
+
records.each do |r|
|
104
|
+
r_array = []
|
105
|
+
self.get_columns.each do |column|
|
106
|
+
r_array << r.send(column[:name])
|
107
|
+
end
|
108
|
+
output_array << r_array
|
109
|
+
end
|
110
|
+
|
111
|
+
# add total_entries method to the result
|
112
|
+
class << output_array
|
113
|
+
attr :total_records, true
|
114
|
+
end
|
115
|
+
total_records_count = config[:data_class_name].constantize.count(conditions)
|
116
|
+
output_array.total_records = total_records_count
|
117
|
+
|
118
|
+
output_array
|
119
|
+
end
|
120
|
+
|
121
|
+
# make params understandable to searchlogic
|
122
|
+
def normalize_params(params)
|
123
|
+
# sorting
|
124
|
+
order_by = if params[:sort]
|
125
|
+
assoc, method = params[:sort].split('__')
|
126
|
+
method.nil? ? assoc : {assoc => method}
|
127
|
+
end
|
128
|
+
|
129
|
+
page = params[:start].to_i/params[:limit].to_i + 1 if params[:limit]
|
130
|
+
{:per_page => params[:limit], :page => page, :order_by => order_by, :order_as => params[:dir]}
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
module Netzke::GridJsBuilder
|
2
|
+
def js_base_class
|
3
|
+
'Ext.grid.EditorGridPanel'
|
4
|
+
end
|
5
|
+
|
6
|
+
def js_bbar
|
7
|
+
<<-JS.l
|
8
|
+
(config.rowsPerPage) ? new Ext.PagingToolbar({
|
9
|
+
pageSize:config.rowsPerPage,
|
10
|
+
items:config.actions,
|
11
|
+
store:ds,
|
12
|
+
emptyMsg:'Empty'}) : config.actions
|
13
|
+
JS
|
14
|
+
end
|
15
|
+
|
16
|
+
def js_default_config
|
17
|
+
super.merge({
|
18
|
+
:store => "ds".l,
|
19
|
+
:cm => "cm".l,
|
20
|
+
:sel_model => "new Ext.grid.RowSelectionModel()".l,
|
21
|
+
:auto_scroll => true,
|
22
|
+
:click_to_edit => 2,
|
23
|
+
:track_mouse_over => true,
|
24
|
+
# :bbar => "config.actions".l,
|
25
|
+
:bbar => js_bbar,
|
26
|
+
|
27
|
+
#custom configs
|
28
|
+
:auto_load_data => true
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
def js_before_constructor
|
33
|
+
<<-JS
|
34
|
+
this.recordConfig = [];
|
35
|
+
|
36
|
+
if (!config.columns) {
|
37
|
+
this.feedback('No columns defined for grid '+config.id);
|
38
|
+
}
|
39
|
+
|
40
|
+
Ext.each(config.columns, function(column){this.recordConfig.push({name:column.name})}, this);
|
41
|
+
this.Row = Ext.data.Record.create(this.recordConfig);
|
42
|
+
var ds = new Ext.data.Store({
|
43
|
+
proxy: this.proxy = new Ext.data.HttpProxy({url:config.interface.getData}),
|
44
|
+
reader: new Ext.data.ArrayReader({root: "data", totalProperty: "total", successProperty: "succes", id:0}, this.Row),
|
45
|
+
remoteSort: true
|
46
|
+
});
|
47
|
+
|
48
|
+
this.cmConfig = [];
|
49
|
+
Ext.each(config.columns, function(c){
|
50
|
+
var editor = c.readOnly ? null : Ext.netzke.editors[c.showsAs](c, config);
|
51
|
+
|
52
|
+
this.cmConfig.push({
|
53
|
+
header: c.label || c.name,
|
54
|
+
dataIndex: c.name,
|
55
|
+
hidden: c.hidden,
|
56
|
+
width: c.width,
|
57
|
+
editor: editor,
|
58
|
+
sortable: true
|
59
|
+
})
|
60
|
+
}, this);
|
61
|
+
|
62
|
+
var cm = new Ext.grid.ColumnModel(this.cmConfig);
|
63
|
+
|
64
|
+
this.addEvents("refresh");
|
65
|
+
|
66
|
+
JS
|
67
|
+
end
|
68
|
+
|
69
|
+
def js_extend_properties
|
70
|
+
{
|
71
|
+
:on_widget_load => <<-JS.l,
|
72
|
+
function(){
|
73
|
+
if (this.initialConfig.autoLoadData) {
|
74
|
+
this.loadWithFeedback({start:0, limit: this.initialConfig.rowsPerPage})
|
75
|
+
}
|
76
|
+
}
|
77
|
+
JS
|
78
|
+
|
79
|
+
:load_with_feedback => <<-JS.l,
|
80
|
+
function(params){
|
81
|
+
if (!params) params = {};
|
82
|
+
var exceptionHandler = function(proxy, options, response, error){
|
83
|
+
if (response.status == 200 && (responseObject = Ext.decode(response.responseText)) && responseObject.flash){
|
84
|
+
this.feedback(responseObject.flash)
|
85
|
+
} else {
|
86
|
+
if (error){
|
87
|
+
this.feedback(error.message);
|
88
|
+
} else {
|
89
|
+
this.feedback(response.statusText)
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}.createDelegate(this);
|
93
|
+
this.store.proxy.on('loadexception', exceptionHandler);
|
94
|
+
this.store.load({callback:function(r, options, success){
|
95
|
+
this.store.proxy.un('loadexception', exceptionHandler);
|
96
|
+
}, params: params, scope:this});
|
97
|
+
}
|
98
|
+
JS
|
99
|
+
|
100
|
+
:add => <<-JS.l,
|
101
|
+
function(){
|
102
|
+
var rowConfig = {};
|
103
|
+
Ext.each(this.initialConfig.columns, function(c){
|
104
|
+
rowConfig[c.name] = c.defaultValue || ''; // FIXME: if the user is happy with all the defaults, the record won't be 'dirty'
|
105
|
+
}, this);
|
106
|
+
|
107
|
+
var r = new this.Row(rowConfig); // TODO: add default values
|
108
|
+
r.set('id', -r.id); // to distinguish new records by negative values
|
109
|
+
this.stopEditing();
|
110
|
+
this.store.add(r);
|
111
|
+
this.store.newRecords = this.store.newRecords || []
|
112
|
+
this.store.newRecords.push(r);
|
113
|
+
// console.info(this.store.newRecords);
|
114
|
+
this.tryStartEditing(this.store.indexOf(r));
|
115
|
+
}
|
116
|
+
JS
|
117
|
+
|
118
|
+
:edit => <<-JS.l,
|
119
|
+
function(){
|
120
|
+
var row = this.getSelectionModel().getSelected();
|
121
|
+
if (row){
|
122
|
+
this.tryStartEditing(this.store.indexOf(row))
|
123
|
+
}
|
124
|
+
}
|
125
|
+
JS
|
126
|
+
|
127
|
+
# try editing the first editable (not hidden, not read-only) sell
|
128
|
+
:try_start_editing => <<-JS.l,
|
129
|
+
function(row){
|
130
|
+
if (row == null) return;
|
131
|
+
var editableColumns = this.getColumnModel().getColumnsBy(function(columnConfig, index){
|
132
|
+
return !columnConfig.hidden && !!columnConfig.editor;
|
133
|
+
});
|
134
|
+
// console.info(editableColumns);
|
135
|
+
var firstEditableColumn = editableColumns[0];
|
136
|
+
if (firstEditableColumn){
|
137
|
+
this.startEditing(row, firstEditableColumn.id);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
JS
|
141
|
+
|
142
|
+
:delete => <<-JS.l,
|
143
|
+
function() {
|
144
|
+
if (this.getSelectionModel().hasSelection()){
|
145
|
+
Ext.Msg.confirm('Confirm', 'Are you sure?', function(btn){
|
146
|
+
if (btn == 'yes') {
|
147
|
+
var records = []
|
148
|
+
this.getSelectionModel().each(function(r){
|
149
|
+
records.push(r.get('id'));
|
150
|
+
}, this);
|
151
|
+
Ext.Ajax.request({
|
152
|
+
url: this.initialConfig.interface.deleteData,
|
153
|
+
params: {records: Ext.encode(records)},
|
154
|
+
success:function(r){
|
155
|
+
var m = Ext.decode(r.responseText);
|
156
|
+
this.loadWithFeedback();
|
157
|
+
this.feedback(m.flash);
|
158
|
+
},
|
159
|
+
scope:this
|
160
|
+
});
|
161
|
+
}
|
162
|
+
}, this);
|
163
|
+
}
|
164
|
+
}
|
165
|
+
JS
|
166
|
+
:submit => <<-JS.l,
|
167
|
+
function(){
|
168
|
+
|
169
|
+
var newRecords = [];
|
170
|
+
if (this.store.newRecords){
|
171
|
+
Ext.each(this.store.newRecords, function(r){
|
172
|
+
newRecords.push(r.getChanges())
|
173
|
+
r.commit() // commit the changes, so that they are not picked up by getModifiedRecords() further down
|
174
|
+
}, this);
|
175
|
+
delete this.store.newRecords;
|
176
|
+
}
|
177
|
+
|
178
|
+
var updatedRecords = [];
|
179
|
+
Ext.each(this.store.getModifiedRecords(),
|
180
|
+
function(record) {
|
181
|
+
var completeRecordData = {};
|
182
|
+
Ext.apply(completeRecordData, Ext.apply(record.getChanges(), {id:record.get('id')}));
|
183
|
+
updatedRecords.push(completeRecordData);
|
184
|
+
},
|
185
|
+
this);
|
186
|
+
|
187
|
+
if (newRecords.length > 0 || updatedRecords.length > 0) {
|
188
|
+
Ext.Ajax.request({
|
189
|
+
url:this.initialConfig.interface.postData,
|
190
|
+
params: {
|
191
|
+
updated_records: Ext.encode(updatedRecords),
|
192
|
+
created_records: Ext.encode(newRecords),
|
193
|
+
filters: this.store.baseParams.filters
|
194
|
+
},
|
195
|
+
success:function(response){
|
196
|
+
var m = Ext.decode(response.responseText);
|
197
|
+
if (m.success) {
|
198
|
+
this.loadWithFeedback();
|
199
|
+
this.store.commitChanges();
|
200
|
+
this.feedback(m.flash);
|
201
|
+
} else {
|
202
|
+
this.feedback(m.flash);
|
203
|
+
}
|
204
|
+
},
|
205
|
+
failure:function(response){
|
206
|
+
this.feedback('Bad response from server');
|
207
|
+
},
|
208
|
+
scope:this
|
209
|
+
});
|
210
|
+
}
|
211
|
+
|
212
|
+
}
|
213
|
+
JS
|
214
|
+
|
215
|
+
:refresh_click => <<-JS.l,
|
216
|
+
function() {
|
217
|
+
// console.info(this);
|
218
|
+
if (this.fireEvent('refresh', this) !== false) this.loadWithFeedback();
|
219
|
+
}
|
220
|
+
JS
|
221
|
+
|
222
|
+
:on_column_resize => <<-JS.l,
|
223
|
+
function(index, size){
|
224
|
+
// var column = this.getColumnModel().getDataIndex(index);
|
225
|
+
Ext.Ajax.request({
|
226
|
+
url:this.initialConfig.interface.resizeColumn,
|
227
|
+
params:{
|
228
|
+
index:index,
|
229
|
+
size:size
|
230
|
+
}
|
231
|
+
})
|
232
|
+
}
|
233
|
+
JS
|
234
|
+
|
235
|
+
:on_column_move => <<-JS.l
|
236
|
+
function(oldIndex, newIndex){
|
237
|
+
Ext.Ajax.request({
|
238
|
+
url:this.initialConfig.interface.moveColumn,
|
239
|
+
params:{
|
240
|
+
old_index:oldIndex,
|
241
|
+
new_index:newIndex
|
242
|
+
}
|
243
|
+
})
|
244
|
+
}
|
245
|
+
JS
|
246
|
+
|
247
|
+
}
|
248
|
+
end
|
249
|
+
end
|