netzke-basepack 0.1.4.1 → 0.2.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.
Files changed (33) hide show
  1. data/CHANGELOG +10 -0
  2. data/Manifest +13 -8
  3. data/README.mdown +10 -10
  4. data/Rakefile +1 -1
  5. data/css/basepack.css +4 -0
  6. data/generators/netzke_basepack/netzke_grid_panel_generator.rb +7 -0
  7. data/generators/netzke_basepack/templates/{create_netzke_grid_columns.rb → create_netzke_grid_panel_columns.rb} +4 -4
  8. data/javascripts/basepack.js +1 -1
  9. data/lib/app/models/{netzke_grid_column.rb → netzke_grid_panel_column.rb} +1 -1
  10. data/lib/netzke-basepack.rb +18 -6
  11. data/lib/netzke/accordion_panel.rb +73 -0
  12. data/lib/netzke/ar_ext.rb +51 -25
  13. data/lib/netzke/border_layout_panel.rb +119 -0
  14. data/lib/netzke/container.rb +5 -5
  15. data/lib/netzke/{grid.rb → grid_panel.rb} +30 -25
  16. data/lib/netzke/{grid_interface.rb → grid_panel_interface.rb} +11 -7
  17. data/lib/netzke/grid_panel_js_builder.rb +282 -0
  18. data/lib/netzke/panel.rb +4 -0
  19. data/lib/netzke/preference_grid.rb +4 -4
  20. data/lib/netzke/properties_tool.rb +51 -40
  21. data/lib/netzke/property_grid.rb +3 -3
  22. data/lib/netzke/wrapper.rb +20 -0
  23. data/netzke-basepack.gemspec +8 -8
  24. data/test/app_root/db/migrate/20081222033440_create_genres.rb +1 -0
  25. data/test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb +1 -1
  26. data/test/ar_ext_test.rb +10 -2
  27. data/test/border_layout_panel_test.rb +28 -0
  28. data/test/{grid_test.rb → grid_panel_test.rb} +5 -4
  29. data/test/netzke_basepack_test.rb +0 -4
  30. metadata +26 -17
  31. data/generators/netzke_basepack/netzke_grid_generator.rb +0 -7
  32. data/lib/netzke/accordion.rb +0 -11
  33. data/lib/netzke/grid_js_builder.rb +0 -276
@@ -20,7 +20,7 @@ module Netzke
20
20
  dep
21
21
  end
22
22
 
23
- def js_before_constructor
23
+ def self.js_before_constructor
24
24
  js_widget_items
25
25
  end
26
26
 
@@ -32,7 +32,7 @@ module Netzke
32
32
  config[:items] || []
33
33
  end
34
34
 
35
- def js_widget_items
35
+ def self.js_widget_items
36
36
  res = ""
37
37
  item_aggregatees.each_pair do |k,v|
38
38
  next if v[:late_aggregation]
@@ -43,7 +43,7 @@ module Netzke
43
43
  res
44
44
  end
45
45
 
46
- def js_items
46
+ def self.js_items
47
47
  items.inject([]) do |a,i|
48
48
  a << {
49
49
  :title => i.to_s.humanize,
@@ -61,7 +61,7 @@ module Netzke
61
61
  end
62
62
  end
63
63
 
64
- def js_extend_properties
64
+ def self.js_extend_properties
65
65
  {
66
66
  # loads widget into the panel if it's not loaded yet
67
67
  :load_item_widget => <<-JS.l,
@@ -74,7 +74,7 @@ module Netzke
74
74
  end
75
75
 
76
76
  protected
77
- def item_aggregatees
77
+ def self.item_aggregatees
78
78
  aggregatees.delete_if{|k,v| !@items.include?(k)}
79
79
  end
80
80
  end
@@ -4,42 +4,47 @@ module Netzke
4
4
  # Functionality:
5
5
  # * data operations - get, post, delete, create
6
6
  # * column resize and move
7
+ # * column hide - TODO
7
8
  # * permissions
8
9
  # * sorting
9
10
  # * pagination
11
+ # * filtering
10
12
  # * properties and column configuration
11
13
  #
12
- class Grid < Base
13
- include GridJsBuilder
14
- include GridInterface
14
+ class GridPanel < Base
15
+ include GridPanelJsBuilder
16
+ include GridPanelInterface
15
17
 
16
- # define connection points between client side and server side of Grid. See implementation of equally named methods in the GridInterface module.
18
+ # define connection points between client side and server side of GridPanel. See implementation of equally named methods in the GridPanelInterface module.
17
19
  interface :get_data, :post_data, :delete_data, :resize_column, :move_column, :get_cb_choices
18
20
 
21
+ # default grid configuration
19
22
  def initial_config
20
23
  {
21
- :ext_config => {:properties => true, :column_filters => true},
22
- :layout_manager => "NetzkeLayout",
23
- :column_resize => true,
24
- :column_move => true
24
+ :ext_config => {
25
+ :config_tool => false,
26
+ :enable_column_filters => Netzke::Base.config[:grid_panel][:filters],
27
+ :enable_column_move => true,
28
+ :enable_column_resize => true,
29
+ :border => true
30
+ },
31
+ :layout_manager => "NetzkeLayout"
25
32
  }
26
33
  end
27
34
 
28
35
  def property_widgets
29
36
  [{
30
- :columns => {
31
- :widget_class_name => "Grid",
32
- :data_class_name => column_manager_class_name,
33
- :ext_config => {:title => false, :properties => false},
34
- :active => true
35
- }
37
+ :name => 'columns',
38
+ :widget_class_name => "GridPanel",
39
+ :data_class_name => column_manager_class_name,
40
+ :ext_config => {:title => false, :config_tool => false},
41
+ :active => true
36
42
  },{
37
- :general => {
38
- :widget_class_name => "PreferenceGrid",
39
- :host_widget_name => @id_name,
40
- :default_properties => available_permissions.map{ |k| {:name => "permissions.#{k}", :value => @permissions[k.to_sym]}},
41
- :ext_config => {:title => false}
42
- }
43
+ :name => 'general',
44
+ :widget_class_name => "PreferenceGrid",
45
+ :host_widget_name => @id_name,
46
+ :default_properties => available_permissions.map{ |k| {:name => "permissions.#{k}", :value => @permissions[k.to_sym]}},
47
+ :ext_config => {:title => false}
43
48
  }]
44
49
  end
45
50
 
@@ -68,7 +73,7 @@ module Netzke
68
73
  end
69
74
 
70
75
  def column_manager_class_name
71
- "NetzkeGridColumn"
76
+ "NetzkeGridPanelColumn"
72
77
  end
73
78
 
74
79
  def column_manager_class
@@ -101,13 +106,13 @@ module Netzke
101
106
 
102
107
  def actions
103
108
  [{
104
- :text => 'Add', :handler => 'add', :disabled => @pref['permissions.create'] == false
109
+ :text => 'Add', :handler => 'add', :disabled => !@permissions[:create]
105
110
  },{
106
- :text => 'Edit', :handler => 'edit', :disabled => @pref['permissions.update'] == false
111
+ :text => 'Edit', :handler => 'edit', :disabled => !@permissions[:update]
107
112
  },{
108
- :text => 'Delete', :handler => 'delete', :disabled => @pref['permissions.delete'] == false
113
+ :text => 'Delete', :handler => 'delete', :disabled => !@permissions[:delete]
109
114
  },{
110
- :text => 'Apply', :handler => 'submit', :disabled => @pref['permissions.update'] == false && @pref['permissions.create'] == false
115
+ :text => 'Apply', :handler => 'submit', :disabled => !@permissions[:update] && !@permissions[:create]
111
116
  }]
112
117
  end
113
118
 
@@ -1,4 +1,4 @@
1
- module Netzke::GridInterface
1
+ module Netzke::GridPanelInterface
2
2
  def post_data(params)
3
3
  [:create, :update].each do |operation|
4
4
  data = JSON.parse(params.delete("#{operation}d_records".to_sym)) if params["#{operation}d_records".to_sym]
@@ -32,16 +32,20 @@ module Netzke::GridInterface
32
32
  end
33
33
 
34
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!
35
+ raise "Called interface_resize_column while not configured to do so" unless config[:ext_config][:enable_column_resize]
36
+ if layout_manager_class
37
+ l_item = layout_manager_class.by_widget(id_name).layout_items[params[:index].to_i]
38
+ l_item.width = params[:size]
39
+ l_item.save!
40
+ end
39
41
  {}
40
42
  end
41
43
 
42
44
  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
+ raise "Called interface_move_column while not configured to do so" unless config[:ext_config][:enable_column_move]
46
+ if layout_manager_class
47
+ layout_manager_class.by_widget(id_name).move_item(params[:old_index].to_i, params[:new_index].to_i)
48
+ end
45
49
  {}
46
50
  end
47
51
 
@@ -0,0 +1,282 @@
1
+ module Netzke::GridPanelJsBuilder
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+ end
5
+
6
+ def js_config
7
+ res = super
8
+ # we pass column config at the time of instantiating the JS class
9
+ res.merge!(:columns => get_columns || config[:columns]) # first try to get columns from DB, then from config
10
+ res.merge!(:data_class_name => config[:data_class_name])
11
+ res
12
+ end
13
+
14
+ module ClassMethods
15
+
16
+ def js_base_class
17
+ 'Ext.grid.EditorGridPanel'
18
+ end
19
+
20
+ def js_bbar
21
+ <<-JS.l
22
+ (config.rowsPerPage) ? new Ext.PagingToolbar({
23
+ pageSize:config.rowsPerPage,
24
+ items:config.actions,
25
+ store:ds,
26
+ emptyMsg:'Empty'}) : config.actions
27
+ JS
28
+ end
29
+
30
+ def js_default_config
31
+ super.merge({
32
+ :store => "ds".l,
33
+ :cm => "cm".l,
34
+ :sel_model => "new Ext.grid.RowSelectionModel()".l,
35
+ :auto_scroll => true,
36
+ :click_to_edit => 2,
37
+ :track_mouse_over => true,
38
+ # :bbar => "config.actions".l,
39
+ :bbar => js_bbar,
40
+ :plugins => "plugins".l,
41
+
42
+ #custom configs
43
+ :auto_load_data => true
44
+ })
45
+ end
46
+
47
+ def js_before_constructor
48
+ <<-JS
49
+ var plugins = [];
50
+ if (!config.columns) this.feedback('No columns defined for grid '+config.id);
51
+ this.recordConfig = [];
52
+ Ext.each(config.columns, function(column){this.recordConfig.push({name:column.name})}, this);
53
+ this.Row = Ext.data.Record.create(this.recordConfig);
54
+
55
+ var ds = new Ext.data.Store({
56
+ proxy: this.proxy = new Ext.data.HttpProxy({url:config.interface.getData}),
57
+ reader: new Ext.data.ArrayReader({root: "data", totalProperty: "total", successProperty: "succes", id:0}, this.Row),
58
+ remoteSort: true,
59
+ listeners:{'loadexception':{
60
+ fn:this.loadExceptionHandler,
61
+ scope:this
62
+ }}
63
+ });
64
+
65
+ this.cmConfig = [];
66
+ Ext.each(config.columns, function(c){
67
+ var editor = (c.readOnly || !config.permissions.update) ? null : Ext.netzke.editors[c.editor](c, config);
68
+
69
+ this.cmConfig.push({
70
+ header: c.label || c.name,
71
+ dataIndex: c.name,
72
+ hidden: c.hidden,
73
+ width: c.width,
74
+ editor: editor,
75
+ sortable: true
76
+ })
77
+ }, this);
78
+
79
+ var cm = new Ext.grid.ColumnModel(this.cmConfig);
80
+
81
+ this.addEvents("refresh");
82
+
83
+ // Filters
84
+ if (config.enableColumnFilters) {
85
+ var filters = []
86
+ Ext.each(config.columns, function(c){
87
+ filters.push({type:Ext.netzke.filterMap[c.editor], dataIndex:c.name})
88
+ })
89
+ var gridFilters = new Ext.grid.GridFilters({filters:filters});
90
+ plugins.push(gridFilters);
91
+ }
92
+
93
+ JS
94
+ end
95
+
96
+ def js_listeners
97
+ super.merge({
98
+ :columnresize => {:fn => "this.onColumnResize".l, :scope => this},
99
+ :columnmove => {:fn => "this.onColumnMove".l, :scope => this}
100
+ })
101
+ end
102
+
103
+ def js_extend_properties
104
+ {
105
+ :on_widget_load => <<-JS.l,
106
+ function(){
107
+ // auto-load
108
+ if (this.initialConfig.autoLoadData) {
109
+ // if we have a paging toolbar, load the first page, otherwise
110
+ if (this.getBottomToolbar().changePage) this.getBottomToolbar().changePage(0); else this.store.load();
111
+ }
112
+ }
113
+ JS
114
+
115
+ :load_exception_handler => <<-JS.l,
116
+ function(proxy, options, response, error){
117
+ if (response.status == 200 && (responseObject = Ext.decode(response.responseText)) && responseObject.flash){
118
+ this.feedback(responseObject.flash)
119
+ } else {
120
+ if (error){
121
+ this.feedback(error.message);
122
+ } else {
123
+ this.feedback(response.statusText)
124
+ }
125
+ }
126
+ }
127
+ JS
128
+
129
+ :add => <<-JS.l,
130
+ function(){
131
+ var rowConfig = {};
132
+ Ext.each(this.initialConfig.columns, function(c){
133
+ rowConfig[c.name] = c.defaultValue || ''; // FIXME: if the user is happy with all the defaults, the record won't be 'dirty'
134
+ }, this);
135
+
136
+ var r = new this.Row(rowConfig); // TODO: add default values
137
+ r.set('id', -r.id); // to distinguish new records by negative values
138
+ this.stopEditing();
139
+ this.store.add(r);
140
+ this.store.newRecords = this.store.newRecords || []
141
+ this.store.newRecords.push(r);
142
+ // console.info(this.store.newRecords);
143
+ this.tryStartEditing(this.store.indexOf(r));
144
+ }
145
+ JS
146
+
147
+ :edit => <<-JS.l,
148
+ function(){
149
+ var row = this.getSelectionModel().getSelected();
150
+ if (row){
151
+ this.tryStartEditing(this.store.indexOf(row))
152
+ }
153
+ }
154
+ JS
155
+
156
+ # try editing the first editable (not hidden, not read-only) sell
157
+ :try_start_editing => <<-JS.l,
158
+ function(row){
159
+ if (row == null) return;
160
+ var editableColumns = this.getColumnModel().getColumnsBy(function(columnConfig, index){
161
+ return !columnConfig.hidden && !!columnConfig.editor;
162
+ });
163
+ // console.info(editableColumns);
164
+ var firstEditableColumn = editableColumns[0];
165
+ if (firstEditableColumn){
166
+ this.startEditing(row, firstEditableColumn.id);
167
+ }
168
+ }
169
+ JS
170
+
171
+ :delete => <<-JS.l,
172
+ function() {
173
+ if (this.getSelectionModel().hasSelection()){
174
+ Ext.Msg.confirm('Confirm', 'Are you sure?', function(btn){
175
+ if (btn == 'yes') {
176
+ var records = []
177
+ this.getSelectionModel().each(function(r){
178
+ records.push(r.get('id'));
179
+ }, this);
180
+ Ext.Ajax.request({
181
+ url: this.initialConfig.interface.deleteData,
182
+ params: {records: Ext.encode(records)},
183
+ success:function(r){
184
+ var m = Ext.decode(r.responseText);
185
+ this.store.reload();
186
+ // this.loadWithFeedback();
187
+ this.feedback(m.flash);
188
+ },
189
+ scope:this
190
+ });
191
+ }
192
+ }, this);
193
+ }
194
+ }
195
+ JS
196
+ :submit => <<-JS.l,
197
+ function(){
198
+
199
+ var newRecords = [];
200
+ if (this.store.newRecords){
201
+ Ext.each(this.store.newRecords, function(r){
202
+ newRecords.push(r.getChanges())
203
+ r.commit() // commit the changes, so that they are not picked up by getModifiedRecords() further down
204
+ }, this);
205
+ delete this.store.newRecords;
206
+ }
207
+
208
+ var updatedRecords = [];
209
+ Ext.each(this.store.getModifiedRecords(),
210
+ function(record) {
211
+ var completeRecordData = {};
212
+ Ext.apply(completeRecordData, Ext.apply(record.getChanges(), {id:record.get('id')}));
213
+ updatedRecords.push(completeRecordData);
214
+ },
215
+ this);
216
+
217
+ if (newRecords.length > 0 || updatedRecords.length > 0) {
218
+ Ext.Ajax.request({
219
+ url:this.initialConfig.interface.postData,
220
+ params: {
221
+ updated_records: Ext.encode(updatedRecords),
222
+ created_records: Ext.encode(newRecords),
223
+ filters: this.store.baseParams.filters
224
+ },
225
+ success:function(response){
226
+ var m = Ext.decode(response.responseText);
227
+ if (m.success) {
228
+ this.store.reload();
229
+ // this.loadWithFeedback();
230
+ this.store.commitChanges();
231
+ this.feedback(m.flash);
232
+ } else {
233
+ this.feedback(m.flash);
234
+ }
235
+ },
236
+ failure:function(response){
237
+ this.feedback('Bad response from server');
238
+ },
239
+ scope:this
240
+ });
241
+ }
242
+
243
+ }
244
+ JS
245
+
246
+ :refresh_click => <<-JS.l,
247
+ function() {
248
+ // console.info(this);
249
+ // if (this.fireEvent('refresh', this) !== false) this.loadWithFeedback();
250
+ if (this.fireEvent('refresh', this) !== false) this.store.reload();
251
+ }
252
+ JS
253
+
254
+ :on_column_resize => <<-JS.l,
255
+ function(index, size){
256
+ Ext.Ajax.request({
257
+ url:this.initialConfig.interface.resizeColumn,
258
+ params:{
259
+ index:index,
260
+ size:size
261
+ }
262
+ })
263
+ }
264
+ JS
265
+
266
+ :on_column_move => <<-JS.l
267
+ function(oldIndex, newIndex){
268
+ Ext.Ajax.request({
269
+ url:this.initialConfig.interface.moveColumn,
270
+ params:{
271
+ old_index:oldIndex,
272
+ new_index:newIndex
273
+ }
274
+ })
275
+ }
276
+ JS
277
+
278
+ }
279
+ end
280
+
281
+ end
282
+ end