skozlov-netzke-basepack 0.1.1.2 → 0.5.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 (81) hide show
  1. data/.autotest +1 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +2 -19
  4. data/README.rdoc +87 -0
  5. data/Rakefile +28 -12
  6. data/TODO.rdoc +7 -0
  7. data/VERSION +1 -0
  8. data/autotest/discover.rb +3 -0
  9. data/init.rb +0 -1
  10. data/javascripts/basepack.js +839 -49
  11. data/lib/app/models/netzke_auto_column.rb +56 -0
  12. data/lib/netzke/accordion_panel.rb +113 -0
  13. data/lib/netzke/active_record/basepack.rb +104 -0
  14. data/lib/netzke/active_record/data_accessor.rb +21 -0
  15. data/lib/netzke/basic_app.rb +325 -0
  16. data/lib/netzke/border_layout_panel.rb +128 -0
  17. data/lib/netzke/configuration_panel.rb +24 -0
  18. data/lib/netzke/data_accessor.rb +71 -0
  19. data/lib/netzke/ext.rb +6 -0
  20. data/lib/netzke/field_model.rb +131 -0
  21. data/lib/netzke/fields_configurator.rb +95 -0
  22. data/lib/netzke/form_panel.rb +214 -0
  23. data/lib/netzke/form_panel_api.rb +74 -0
  24. data/lib/netzke/form_panel_extras/javascripts/xcheckbox.js +82 -0
  25. data/lib/netzke/form_panel_js.rb +129 -0
  26. data/lib/netzke/grid_panel.rb +442 -0
  27. data/lib/netzke/grid_panel_api.rb +352 -0
  28. data/lib/netzke/grid_panel_extras/javascripts/check-column.js +33 -0
  29. data/{javascripts → lib/netzke/grid_panel_extras/javascripts}/filters.js +0 -0
  30. data/lib/netzke/grid_panel_extras/javascripts/rows-dd.js +280 -0
  31. data/lib/netzke/grid_panel_js.rb +721 -0
  32. data/lib/netzke/panel.rb +13 -0
  33. data/lib/netzke/plugins/configuration_tool.rb +121 -0
  34. data/lib/netzke/property_editor.rb +105 -0
  35. data/lib/netzke/property_editor_extras/helper_model.rb +126 -0
  36. data/lib/netzke/search_panel.rb +62 -0
  37. data/lib/netzke/tab_panel.rb +160 -0
  38. data/lib/netzke/table_editor.rb +118 -0
  39. data/lib/netzke/tree_panel.rb +73 -0
  40. data/lib/netzke/wrapper.rb +42 -0
  41. data/lib/netzke-basepack.rb +9 -15
  42. data/netzke-basepack.gemspec +147 -20
  43. data/stylesheets/basepack.css +26 -0
  44. data/test/app_root/app/models/book.rb +1 -1
  45. data/test/app_root/config/environment.rb +1 -0
  46. data/test/app_root/db/migrate/20081222033440_create_genres.rb +1 -0
  47. data/test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb +1 -1
  48. data/test/app_root/db/migrate/20090102223630_create_netzke_layouts.rb +14 -0
  49. data/test/app_root/vendor/plugins/acts_as_list/README +23 -0
  50. data/test/app_root/vendor/plugins/acts_as_list/init.rb +3 -0
  51. data/test/app_root/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb +256 -0
  52. data/test/test_helper.rb +1 -2
  53. data/test/unit/accordion_panel_test.rb +20 -0
  54. data/test/unit/active_record_basepack_test.rb +54 -0
  55. data/test/unit/grid_panel_test.rb +43 -0
  56. data/test/unit/helper_model_test.rb +30 -0
  57. data/test/unit/netzke_basepack_test.rb +4 -0
  58. data/test/unit/tab_panel_test.rb +21 -0
  59. metadata +96 -72
  60. data/CHANGELOG +0 -14
  61. data/Manifest +0 -65
  62. data/README.mdown +0 -18
  63. data/generators/netzke_basepack/USAGE +0 -8
  64. data/generators/netzke_basepack/netzke_basepack_generator.rb +0 -8
  65. data/generators/netzke_basepack/netzke_grid_generator.rb +0 -7
  66. data/generators/netzke_basepack/templates/create_netzke_grid_columns.rb +0 -21
  67. data/lib/app/models/netzke_grid_column.rb +0 -23
  68. data/lib/netzke/accordion.rb +0 -11
  69. data/lib/netzke/ar_ext.rb +0 -163
  70. data/lib/netzke/column.rb +0 -43
  71. data/lib/netzke/container.rb +0 -81
  72. data/lib/netzke/grid.rb +0 -120
  73. data/lib/netzke/grid_interface.rb +0 -156
  74. data/lib/netzke/grid_js_builder.rb +0 -276
  75. data/lib/netzke/preference_grid.rb +0 -43
  76. data/lib/netzke/properties_tool.rb +0 -66
  77. data/lib/netzke/property_grid.rb +0 -60
  78. data/test/ar_ext_test.rb +0 -39
  79. data/test/column_test.rb +0 -27
  80. data/test/grid_test.rb +0 -43
  81. data/test/netzke_basepack_test.rb +0 -8
@@ -1,156 +0,0 @@
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
- def process_data(data, operation)
61
- if @permissions[operation]
62
- klass = config[:data_class_name].constantize
63
- modified_records = 0
64
- data.each do |record_hash|
65
- record = operation == :create ? klass.create : klass.find(record_hash.delete('id'))
66
- logger.debug { "!!! record: #{record.inspect}" }
67
- success = true
68
- exception = nil
69
-
70
- # process all attirubutes for the same record (OPTIMIZE: we can use update_attributes separately for regular attributes to speed things up)
71
- record_hash.each_pair do |k,v|
72
- begin
73
- record.send("#{k}=",v)
74
- rescue ArgumentError => exc
75
- flash :error => exc.message
76
- success = false
77
- break
78
- end
79
- end
80
-
81
- # try to save
82
- modified_records += 1 if success && record.save
83
-
84
- # flash eventual errors
85
- record.errors.each_full do |msg|
86
- flash :error => msg
87
- end
88
-
89
- flash :notice => "#{operation.to_s.capitalize}d #{modified_records} records"
90
- end
91
- else
92
- flash :error => "You don't have permissions to #{operation} data"
93
- end
94
- end
95
-
96
- # get records
97
- def get_records(params)
98
- search_params = normalize_params(params)
99
- raise ArgumentError, "No data_class_name specified for widget '#{config[:name]}'" if !config[:data_class_name]
100
- records = config[:data_class_name].constantize.all(search_params.clone) # clone needed as searchlogic removes :conditions key from the hash
101
- output_array = []
102
- records.each do |r|
103
- r_array = []
104
- self.get_columns.each do |column|
105
- r_array << r.send(column[:name])
106
- end
107
- output_array << r_array
108
- end
109
-
110
- # add total_entries accessor to the result
111
- class << output_array
112
- attr :total_records, true
113
- end
114
- total_records_count = config[:data_class_name].constantize.count(search_params)
115
- output_array.total_records = total_records_count
116
-
117
- output_array
118
- end
119
-
120
- def convert_filters(column_filter)
121
- res = {}
122
- column_filter.each_pair do |k,v|
123
- field = v["field"]
124
- case v["data"]["type"]
125
- when "string"
126
- field << "_contains"
127
- when "numeric"
128
- field << "_#{v["data"]["comparison"]}"
129
- end
130
- value = v["data"]["value"]
131
- res.merge!({field => value})
132
- end
133
- res
134
- end
135
-
136
- # make params understandable to searchlogic
137
- def normalize_params(params)
138
- # filters
139
- conditions = params[:filter] && convert_filters(params[:filter])
140
-
141
- normalized_conditions = {}
142
- conditions && conditions.each_pair do |k, v|
143
- assoc, method = k.split('__')
144
- normalized_conditions.merge!(method.nil? ? {assoc => v} : {assoc => {method => v}})
145
- end
146
-
147
- # sorting
148
- order_by = if params[:sort]
149
- assoc, method = params[:sort].split('__')
150
- method.nil? ? assoc : {assoc => method}
151
- end
152
-
153
- page = params[:start].to_i/params[:limit].to_i + 1 if params[:limit]
154
- {:per_page => params[:limit], :page => page, :order_by => order_by, :order_as => params[:dir], :conditions => normalized_conditions}
155
- end
156
- end
@@ -1,276 +0,0 @@
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
- :plugins => "plugins".l,
27
-
28
- #custom configs
29
- :auto_load_data => true
30
- })
31
- end
32
-
33
- def js_before_constructor
34
- <<-JS
35
- var plugins = [];
36
- if (!config.columns) this.feedback('No columns defined for grid '+config.id);
37
- this.recordConfig = [];
38
- Ext.each(config.columns, function(column){this.recordConfig.push({name:column.name})}, this);
39
- this.Row = Ext.data.Record.create(this.recordConfig);
40
-
41
- var ds = new Ext.data.Store({
42
- proxy: this.proxy = new Ext.data.HttpProxy({url:config.interface.getData}),
43
- reader: new Ext.data.ArrayReader({root: "data", totalProperty: "total", successProperty: "succes", id:0}, this.Row),
44
- remoteSort: true,
45
- listeners:{'loadexception':{
46
- fn:this.loadExceptionHandler,
47
- scope:this
48
- }}
49
- });
50
-
51
- this.cmConfig = [];
52
- Ext.each(config.columns, function(c){
53
- var editor = c.readOnly ? null : Ext.netzke.editors[c.showsAs](c, config);
54
-
55
- this.cmConfig.push({
56
- header: c.label || c.name,
57
- dataIndex: c.name,
58
- hidden: c.hidden,
59
- width: c.width,
60
- editor: editor,
61
- sortable: true
62
- })
63
- }, this);
64
-
65
- var cm = new Ext.grid.ColumnModel(this.cmConfig);
66
-
67
- this.addEvents("refresh");
68
-
69
- // Filters
70
- if (config.columnFilters) {
71
- var filters = []
72
- Ext.each(config.columns, function(c){
73
- filters.push({type:Ext.netzke.filterMap[c.showsAs], dataIndex:c.name})
74
- })
75
- var gridFilters = new Ext.grid.GridFilters({filters:filters});
76
- plugins.push(gridFilters);
77
- }
78
-
79
- JS
80
- end
81
-
82
- def js_config
83
- res = super
84
- # we pass column config at the time of instantiating the JS class
85
- res.merge!(:columns => get_columns || config[:columns]) # first try to get columns from DB, then from config
86
- res.merge!(:data_class_name => config[:data_class_name])
87
- res
88
- end
89
-
90
- def js_listeners
91
- super.merge({
92
- :columnresize => (config[:column_resize] ? {:fn => "this.onColumnResize".l, :scope => this} : nil),
93
- :columnmove => (config[:column_move] ? {:fn => "this.onColumnMove".l, :scope => this} : nil)
94
- })
95
- end
96
-
97
-
98
- def js_extend_properties
99
- {
100
- :on_widget_load => <<-JS.l,
101
- function(){
102
- // auto-load
103
- if (this.initialConfig.autoLoadData) {
104
- // if we have a paging toolbar, load the first page, otherwise
105
- if (this.getBottomToolbar().changePage) this.getBottomToolbar().changePage(0); else this.store.load();
106
- }
107
- }
108
- JS
109
-
110
- :load_exception_handler => <<-JS.l,
111
- function(proxy, options, response, error){
112
- if (response.status == 200 && (responseObject = Ext.decode(response.responseText)) && responseObject.flash){
113
- this.feedback(responseObject.flash)
114
- } else {
115
- if (error){
116
- this.feedback(error.message);
117
- } else {
118
- this.feedback(response.statusText)
119
- }
120
- }
121
- }
122
- JS
123
-
124
- :add => <<-JS.l,
125
- function(){
126
- var rowConfig = {};
127
- Ext.each(this.initialConfig.columns, function(c){
128
- rowConfig[c.name] = c.defaultValue || ''; // FIXME: if the user is happy with all the defaults, the record won't be 'dirty'
129
- }, this);
130
-
131
- var r = new this.Row(rowConfig); // TODO: add default values
132
- r.set('id', -r.id); // to distinguish new records by negative values
133
- this.stopEditing();
134
- this.store.add(r);
135
- this.store.newRecords = this.store.newRecords || []
136
- this.store.newRecords.push(r);
137
- // console.info(this.store.newRecords);
138
- this.tryStartEditing(this.store.indexOf(r));
139
- }
140
- JS
141
-
142
- :edit => <<-JS.l,
143
- function(){
144
- var row = this.getSelectionModel().getSelected();
145
- if (row){
146
- this.tryStartEditing(this.store.indexOf(row))
147
- }
148
- }
149
- JS
150
-
151
- # try editing the first editable (not hidden, not read-only) sell
152
- :try_start_editing => <<-JS.l,
153
- function(row){
154
- if (row == null) return;
155
- var editableColumns = this.getColumnModel().getColumnsBy(function(columnConfig, index){
156
- return !columnConfig.hidden && !!columnConfig.editor;
157
- });
158
- // console.info(editableColumns);
159
- var firstEditableColumn = editableColumns[0];
160
- if (firstEditableColumn){
161
- this.startEditing(row, firstEditableColumn.id);
162
- }
163
- }
164
- JS
165
-
166
- :delete => <<-JS.l,
167
- function() {
168
- if (this.getSelectionModel().hasSelection()){
169
- Ext.Msg.confirm('Confirm', 'Are you sure?', function(btn){
170
- if (btn == 'yes') {
171
- var records = []
172
- this.getSelectionModel().each(function(r){
173
- records.push(r.get('id'));
174
- }, this);
175
- Ext.Ajax.request({
176
- url: this.initialConfig.interface.deleteData,
177
- params: {records: Ext.encode(records)},
178
- success:function(r){
179
- var m = Ext.decode(r.responseText);
180
- this.store.reload();
181
- // this.loadWithFeedback();
182
- this.feedback(m.flash);
183
- },
184
- scope:this
185
- });
186
- }
187
- }, this);
188
- }
189
- }
190
- JS
191
- :submit => <<-JS.l,
192
- function(){
193
-
194
- var newRecords = [];
195
- if (this.store.newRecords){
196
- Ext.each(this.store.newRecords, function(r){
197
- newRecords.push(r.getChanges())
198
- r.commit() // commit the changes, so that they are not picked up by getModifiedRecords() further down
199
- }, this);
200
- delete this.store.newRecords;
201
- }
202
-
203
- var updatedRecords = [];
204
- Ext.each(this.store.getModifiedRecords(),
205
- function(record) {
206
- var completeRecordData = {};
207
- Ext.apply(completeRecordData, Ext.apply(record.getChanges(), {id:record.get('id')}));
208
- updatedRecords.push(completeRecordData);
209
- },
210
- this);
211
-
212
- if (newRecords.length > 0 || updatedRecords.length > 0) {
213
- Ext.Ajax.request({
214
- url:this.initialConfig.interface.postData,
215
- params: {
216
- updated_records: Ext.encode(updatedRecords),
217
- created_records: Ext.encode(newRecords),
218
- filters: this.store.baseParams.filters
219
- },
220
- success:function(response){
221
- var m = Ext.decode(response.responseText);
222
- if (m.success) {
223
- this.store.reload();
224
- // this.loadWithFeedback();
225
- this.store.commitChanges();
226
- this.feedback(m.flash);
227
- } else {
228
- this.feedback(m.flash);
229
- }
230
- },
231
- failure:function(response){
232
- this.feedback('Bad response from server');
233
- },
234
- scope:this
235
- });
236
- }
237
-
238
- }
239
- JS
240
-
241
- :refresh_click => <<-JS.l,
242
- function() {
243
- // console.info(this);
244
- // if (this.fireEvent('refresh', this) !== false) this.loadWithFeedback();
245
- if (this.fireEvent('refresh', this) !== false) this.store.reload();
246
- }
247
- JS
248
-
249
- :on_column_resize => <<-JS.l,
250
- function(index, size){
251
- // var column = this.getColumnModel().getDataIndex(index);
252
- Ext.Ajax.request({
253
- url:this.initialConfig.interface.resizeColumn,
254
- params:{
255
- index:index,
256
- size:size
257
- }
258
- })
259
- }
260
- JS
261
-
262
- :on_column_move => <<-JS.l
263
- function(oldIndex, newIndex){
264
- Ext.Ajax.request({
265
- url:this.initialConfig.interface.moveColumn,
266
- params:{
267
- old_index:oldIndex,
268
- new_index:newIndex
269
- }
270
- })
271
- }
272
- JS
273
-
274
- }
275
- end
276
- end
@@ -1,43 +0,0 @@
1
- module Netzke
2
- # GUI for Preference class
3
- class PreferenceGrid < PropertyGrid
4
- def initialize(*args)
5
- super
6
- config[:default_properties] ||= []
7
- NetzkePreference.custom_field = config[:host_widget_name]
8
-
9
- # Create default properties
10
- config[:default_properties].each do |p|
11
- NetzkePreference[p[:name]] = p[:value] if NetzkePreference[p[:name]].nil?
12
- end
13
- end
14
-
15
- def load_source(params = {})
16
- # config[:data_class_name] = 'NetzkePreference'
17
- config[:conditions] ||= {}
18
-
19
- data_class = NetzkePreference
20
- records = data_class.find(:all, :conditions => {:custom_field => config[:host_widget_name]})
21
-
22
- NetzkePreference.custom_field = config[:host_widget_name]
23
-
24
- source = {}
25
- records.each do |r|
26
- source.merge!(r.name => NetzkePreference[r.name])
27
- end
28
-
29
- {:source => source}
30
- end
31
-
32
- def submit_source(params = {})
33
- data = JSON.parse(params[:data])
34
- NetzkePreference.custom_field = config[:host_widget_name]
35
- data.each_pair do |k,v|
36
- NetzkePreference[k.underscore] = v
37
- end
38
-
39
- {:success => true, :flash => @flash}
40
- end
41
-
42
- end
43
- end