netzke-basepack 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/CHANGELOG.rdoc +27 -2
  2. data/TODO.rdoc +1 -5
  3. data/app/models/netzke_persistent_array_auto_model.rb +0 -1
  4. data/features/components_in_view.feature +11 -0
  5. data/features/form_panel.feature +49 -0
  6. data/features/grid_panel.feature +32 -1
  7. data/features/i18n.feature +18 -0
  8. data/features/nested_attributes.feature +23 -0
  9. data/features/search_in_grid.feature +9 -9
  10. data/features/simple_app.feature +10 -0
  11. data/features/step_definitions/grid_panel_steps.rb +23 -0
  12. data/features/support/paths.rb +6 -0
  13. data/features/support/pickle.rb +0 -1
  14. data/features/virtual_attributes.feature +20 -0
  15. data/javascripts/basepack.js +166 -243
  16. data/lib/netzke-basepack.rb +3 -3
  17. data/lib/netzke/active_record.rb +6 -7
  18. data/lib/netzke/active_record/attributes.rb +214 -143
  19. data/lib/netzke/active_record/combobox_options.rb +12 -10
  20. data/lib/netzke/basepack.rb +6 -3
  21. data/lib/netzke/basepack/accordion_panel.rb +4 -2
  22. data/lib/netzke/basepack/auth_app.rb +152 -0
  23. data/lib/netzke/basepack/basic_app.rb +2 -262
  24. data/lib/netzke/basepack/form_panel.rb +35 -27
  25. data/lib/netzke/basepack/form_panel/fields.rb +35 -17
  26. data/lib/netzke/basepack/form_panel/javascripts/comma_list_cbg.js +59 -0
  27. data/lib/netzke/basepack/form_panel/javascripts/display_mode.js +62 -0
  28. data/lib/netzke/basepack/form_panel/javascripts/main.js +138 -0
  29. data/lib/netzke/basepack/form_panel/javascripts/n_radio_group.js +25 -0
  30. data/lib/netzke/basepack/form_panel/services.rb +12 -9
  31. data/lib/netzke/basepack/grid_panel.rb +87 -53
  32. data/lib/netzke/basepack/grid_panel/columns.rb +60 -15
  33. data/lib/netzke/basepack/grid_panel/javascripts/advanced_search.js +2 -64
  34. data/lib/netzke/basepack/grid_panel/javascripts/edit_in_form.js +2 -2
  35. data/lib/netzke/basepack/grid_panel/javascripts/{pre.js → main.js} +35 -17
  36. data/lib/netzke/basepack/grid_panel/javascripts/misc.js +4 -0
  37. data/lib/netzke/basepack/grid_panel/services.rb +17 -14
  38. data/lib/netzke/basepack/paging_form_panel.rb +92 -0
  39. data/lib/netzke/basepack/simple_app.rb +71 -0
  40. data/lib/netzke/basepack/simple_app/javascripts/main.js +53 -0
  41. data/lib/netzke/basepack/{basic_app → simple_app/javascripts}/statusbar_ext.js +0 -0
  42. data/lib/netzke/basepack/tab_panel.rb +2 -12
  43. data/lib/netzke/basepack/tab_panel/javascripts/main.js +11 -0
  44. data/lib/netzke/basepack/version.rb +2 -2
  45. data/lib/netzke/basepack/window.rb +6 -7
  46. data/lib/netzke/basepack/wrap_lazy_loaded.rb +3 -1
  47. data/lib/netzke/data_accessor.rb +25 -14
  48. data/lib/netzke/ext.rb +1 -1
  49. data/locales/en.yml +22 -0
  50. data/netzke-basepack.gemspec +66 -12
  51. data/spec/active_record/attributes_spec.rb +31 -2
  52. data/spec/factories.rb +16 -1
  53. data/test/rails_app/Gemfile +2 -2
  54. data/test/rails_app/Gemfile.lock +76 -77
  55. data/test/rails_app/app/components/author_grid.rb +7 -0
  56. data/test/rails_app/app/components/book_form.rb +24 -0
  57. data/test/rails_app/app/components/book_grid.rb +6 -1
  58. data/test/rails_app/app/components/book_grid_with_default_values.rb +11 -0
  59. data/test/rails_app/app/components/book_grid_with_nested_attributes.rb +13 -0
  60. data/test/rails_app/app/components/book_grid_with_virtual_attributes.rb +22 -0
  61. data/test/rails_app/app/components/book_paging_form_panel.rb +20 -0
  62. data/test/rails_app/app/components/book_presentation.rb +18 -0
  63. data/test/rails_app/app/components/books_bound_to_author.rb +10 -0
  64. data/test/rails_app/app/components/form_without_model.rb +19 -0
  65. data/test/rails_app/app/components/lockable_book_form.rb +17 -0
  66. data/test/rails_app/app/components/lockable_user_form.rb +7 -0
  67. data/test/rails_app/app/components/simple_window.rb +10 -0
  68. data/test/rails_app/app/components/some_accordion_panel.rb +22 -0
  69. data/test/rails_app/app/components/{simple_basic_app.rb → some_auth_app.rb} +3 -3
  70. data/test/rails_app/app/components/some_border_layout.rb +10 -7
  71. data/test/rails_app/app/components/some_simple_app.rb +34 -0
  72. data/test/rails_app/app/components/some_tab_panel.rb +16 -11
  73. data/test/rails_app/app/components/user_form.rb +11 -4
  74. data/test/rails_app/app/components/user_grid.rb +7 -1
  75. data/test/rails_app/app/components/window_component_loader.rb +1 -0
  76. data/test/rails_app/app/controllers/application_controller.rb +6 -0
  77. data/test/rails_app/app/controllers/components_controller.rb +3 -3
  78. data/test/rails_app/app/controllers/welcome_controller.rb +2 -2
  79. data/test/rails_app/app/helpers/embedded_components_helper.rb +2 -0
  80. data/test/rails_app/app/models/address.rb +3 -0
  81. data/test/rails_app/app/models/author.rb +2 -0
  82. data/test/rails_app/app/models/book.rb +1 -0
  83. data/test/rails_app/app/models/user.rb +1 -2
  84. data/test/rails_app/app/views/components/simple_panel.html.erb +1 -0
  85. data/test/rails_app/app/views/layouts/nested.html.erb +5 -0
  86. data/test/rails_app/config/application.rb +1 -1
  87. data/test/rails_app/config/initializers/netzke.rb +0 -4
  88. data/test/rails_app/config/locales/es.yml +16 -0
  89. data/test/rails_app/config/routes.rb +4 -1
  90. data/test/rails_app/db/development_structure.sql +33 -4
  91. data/test/rails_app/db/migrate/20101026190021_create_books.rb +2 -0
  92. data/test/rails_app/db/migrate/20110101143818_create_addresses.rb +17 -0
  93. data/test/rails_app/db/schema.rb +33 -1
  94. data/test/rails_app/spec/controllers/embedded_components_controller_spec.rb +12 -0
  95. data/test/rails_app/spec/helpers/embedded_components_helper_spec.rb +15 -0
  96. data/test/rails_app/spec/models/address_spec.rb +5 -0
  97. data/test/rails_app/spec/views/embedded_components/index.html.erb_spec.rb +5 -0
  98. metadata +67 -13
  99. data/features/basic_app.feature +0 -12
  100. data/lib/netzke/active_record/association_attributes.rb +0 -102
  101. data/lib/netzke/basepack/form_panel/javascripts/pre.js +0 -76
  102. data/lib/netzke/basepack/form_panel/javascripts/xcheckbox.js +0 -82
  103. data/lib/netzke/basepack/grid_panel/javascript.rb +0 -69
  104. data/locale/en.yml +0 -16
@@ -1,6 +1,5 @@
1
1
  require "netzke/basepack/grid_panel/columns"
2
2
  require "netzke/basepack/grid_panel/services"
3
- require "netzke/basepack/grid_panel/javascript"
4
3
  # require "netzke/basepack/plugins/configuration_tool"
5
4
  # require "data_accessor"
6
5
 
@@ -50,11 +49,11 @@ module Netzke
50
49
  # When it's a hash, it's a conditions hash (passed directly to +where+).
51
50
  # When it's an array, it's expanded into an SQL statement with arguments (passed directly to +where+), e.g.:
52
51
  #
53
- # :query => ["id > ?", 100])
52
+ # :scope => ["id > ?", 100])
54
53
  #
55
54
  # When it's a Proc, it's passed the model class, and is expected to return a ActiveRecord::Relation, e.g.:
56
55
  #
57
- # :query => { |klass| klass.where(:id.gt => 100).order(:created_at) }
56
+ # :scope => { |rel| rel.where(:id.gt => 100).order(:created_at) }
58
57
  #
59
58
  # * <tt>:enable_column_filters</tt> - enable filters in column's context menu
60
59
  # * <tt>:enable_edit_in_form</tt> - provide buttons into the toolbar that activate editing/adding records via a form
@@ -70,15 +69,36 @@ module Netzke
70
69
  # * <tt>:columns</tt> - an array of columns to be displayed in the grid; each column may be represented by a symbol (representing the model's attribute name), or a hash (when extra configuration is needed)
71
70
  #
72
71
  # == Columns
73
- # Each column supports the option :sorting_scope, which defines a scope used for sorting the column. This option would be
74
- # useful for virtual columns for example. The scope will get one parameter which contains the direction (:asc or :desc)
75
- # Example:
76
- # { :name => "complete_user_name", :sorting_scope => :sort_user_by_full_name }
77
- # class User < ActiveRecord::Base
78
- # scope :sort_user_by_full_name, lambda { |dir|
72
+ # Columns are configured by passing an array to the +columns+ option. Each element in the array is either the name of model's (virtual) attribute, or a column configuration hash.
73
+ # The column configuration hash recognizes the following options:
74
+ #
75
+ # * +name+ - name of the column, that may correspond to model's (virtual) attribute
76
+ # * +read_only+ - a boolean that defines if the cells in the column should be editable
77
+ # * +editable+ - same as +read_only+, but in reverse (takes precedence over +read_only+)
78
+ # * +getter+ - a lambda that receives a record as a parameter, and is expected to return a string that will be printed in the cell (can be HTML code)
79
+ # * +setter+ - a lambda that receives a record as first parameter, and the value passed from the cell as the second parameter, and is expected to modify the record accordingly
80
+ #
81
+ # * +sorting_scope+ - the name of the scope used for sorting the column. This can be useful for virtual columns for example. The scope will get one parameter specifying the direction (:asc or :desc). Example:
82
+ #
83
+ # columns => [{ :name => "complete_user_name", :sorting_scope => :sort_user_by_full_name }, ...]
84
+ #
85
+ # class User < ActiveRecord::Base
86
+ # scope :sort_user_by_full_name, lambda { |dir|
79
87
  # order("users.first_name #{dir.to_s}, users.last_name #{dir.to_s}")
80
- # }
81
- # end
88
+ # }
89
+ # end
90
+ # Besides these options, a column can receive any meaningful config option understood by Ext.grid.Column (http://dev.sencha.com/deploy/dev/docs/?class=Ext.grid.Column)
91
+ #
92
+ # == Actions
93
+ # You can override GridPanel's actions to change their text, icons, and tooltips (see http://api.netzke.org/core/Netzke/Actions.html). You can also use these actions when configuring menus and toolbars.
94
+ # GridPanel implements the following actions:
95
+ # * +add+
96
+ # * +del+
97
+ # * +edit+
98
+ # * +apply+
99
+ # * +add_in_form+
100
+ # * +edit_in_form+
101
+ # * +search+
82
102
  class GridPanel < Netzke::Base
83
103
  # Class-level configuration. These options directly influence the amount of generated
84
104
  # javascript code for this component's class. For example, if you don't want filters for the grid,
@@ -110,7 +130,6 @@ module Netzke
110
130
  :tools => %w{ refresh },
111
131
  }
112
132
 
113
- include self::Javascript
114
133
  include self::Services
115
134
  include self::Columns
116
135
 
@@ -129,16 +148,20 @@ module Netzke
129
148
  # super(*args)
130
149
  # end
131
150
 
132
- # Include extra javascript that we depend on
133
- def self.include_js
134
- res = ["#{File.dirname(__FILE__)}/grid_panel/javascripts/pre.js"]
135
-
136
- # Optional edit in form functionality
137
- res << "#{File.dirname(__FILE__)}/grid_panel/javascripts/edit_in_form.js" if edit_in_form_available
151
+ js_base_class "Ext.grid.EditorGridPanel"
152
+ js_mixin :main
153
+ js_mixin :advanced_search if extended_search_available
154
+ js_mixin :edit_in_form if edit_in_form_available
138
155
 
139
- # Optional extended search functionality
140
- res << "#{File.dirname(__FILE__)}/grid_panel/javascripts/advanced_search.js" if extended_search_available
156
+ # I18n used in JavaScript
157
+ js_property :i18n, {
158
+ :are_you_sure => I18n.translate("netzke.basepack.generic.are_you_sure"),
159
+ :confirm => I18n.translate("netzke.basepack.generic.confirm")
160
+ }
141
161
 
162
+ # Include extra javascript that we depend on
163
+ def self.include_js
164
+ res = []
142
165
  ext_examples = Netzke::Core.ext_location.join("examples")
143
166
 
144
167
  # Checkcolumn
@@ -153,6 +176,9 @@ module Netzke
153
176
  %w{Boolean Date List Numeric String}.unshift("").each do |f|
154
177
  res << ext_examples + "ux/gridfilters/filter/#{f}Filter.js"
155
178
  end
179
+
180
+ # Fix
181
+ res << "#{File.dirname(__FILE__)}/grid_panel/javascripts/misc.js"
156
182
  end
157
183
 
158
184
  # DD
@@ -179,16 +205,24 @@ module Netzke
179
205
  end
180
206
 
181
207
 
208
+ # The result of this method (a hash) is converted to a JSON object and passed as the configuration parameter
209
+ # to the constructor of our JavaScript class. Override it when you want to pass any extra configuration
210
+ # to the JavaScript side.
211
+ def js_config
212
+ super.merge({
213
+ :bbar => config.has_key?(:bbar) ? config[:bbar] : default_bbar,
214
+ :context_menu => config.has_key?(:context_menu) ? config[:context_menu] : default_context_menu,
215
+ :columns => columns, # columns
216
+ :model => config[:model], # the model name
217
+ :inline_data => (get_data if config[:load_inline_data]), # inline data (loaded along with the grid panel)
218
+ :pri => data_class.primary_key # table primary key name
219
+ })
220
+ end
221
+
182
222
  def default_bbar
183
223
  res = %w{ add edit apply del }.map(&:to_sym).map(&:action)
184
224
  res << "-" << :add_in_form.action << :edit_in_form.action if config[:enable_edit_in_form]
185
225
  res << "-" << :search.action if config[:enable_extended_search]
186
- # config[:enable_extended_search] && res << "-" << {
187
- # :text => "Search",
188
- # :handler => :on_search,
189
- # :enable_toggle => true,
190
- # :icon => :find
191
- # }
192
226
  res
193
227
  end
194
228
 
@@ -218,52 +252,52 @@ module Netzke
218
252
 
219
253
  action :add do
220
254
  {
221
- :text => I18n.t('netzke.basepack.grid_panel.add', :default => "Add"),
222
- :tooltip => I18n.t('netzke.basepack.grid_panel.add', :default => "Add"),
255
+ :text => I18n.t('netzke.basepack.grid_panel.actions.add'),
256
+ :tooltip => I18n.t('netzke.basepack.grid_panel.actions.add'),
223
257
  :disabled => config[:prohibit_create],
224
258
  :icon => :add
225
259
  }
226
260
  end
227
261
 
228
262
  action :edit, {
229
- :text => I18n.t('netzke.basepack.grid_panel.edit', :default => "Edit"),
230
- :tooltip => I18n.t('netzke.basepack.grid_panel.edit', :default => "Edit"),
263
+ :text => I18n.t('netzke.basepack.grid_panel.actions.edit'),
264
+ :tooltip => I18n.t('netzke.basepack.grid_panel.actions.edit'),
231
265
  :disabled => true,
232
266
  :icon => :table_edit
233
267
  }
234
268
 
235
269
  action :del, {
236
- :text => I18n.t('netzke.basepack.grid_panel.delete', :default => "Delete"),
237
- :tooltip => I18n.t('netzke.basepack.grid_panel.delete', :default => "Delete"),
270
+ :text => I18n.t('netzke.basepack.grid_panel.actions.del'),
271
+ :tooltip => I18n.t('netzke.basepack.grid_panel.actions.del'),
238
272
  :disabled => true,
239
273
  :icon => :table_row_delete
240
274
  }
241
275
 
242
276
  action :apply do
243
277
  {
244
- :text => I18n.t('netzke.basepack.grid_panel.apply', :default => "Apply"),
245
- :tooltip => I18n.t('netzke.basepack.grid_panel.apply', :default => "Apply"),
278
+ :text => I18n.t('netzke.basepack.grid_panel.actions.apply'),
279
+ :tooltip => I18n.t('netzke.basepack.grid_panel.actions.apply'),
246
280
  :disabled => config[:prohibit_update] && config[:prohibit_create],
247
281
  :icon => :tick
248
282
  }
249
283
  end
250
284
 
251
285
  action :add_in_form, {
252
- :text => I18n.t('netzke.basepack.grid_panel.add_in_form', :default => "Add in form"),
253
- :tooltip => I18n.t('netzke.basepack.grid_panel.add_in_form', :default => "Add in form"),
286
+ :text => I18n.t('netzke.basepack.grid_panel.actions.add_in_form'),
287
+ :tooltip => I18n.t('netzke.basepack.grid_panel.actions.add_in_form'),
254
288
  :icon => :application_form_add
255
289
  }
256
290
 
257
291
  action :edit_in_form, {
258
- :text => I18n.t('netzke.basepack.grid_panel.edit_in_form', :default => "Edit in form"),
259
- :tooltip => I18n.t('netzke.basepack.grid_panel.edit_in_form', :default => "Edit in form"),
292
+ :text => I18n.t('netzke.basepack.grid_panel.actions.edit_in_form'),
293
+ :tooltip => I18n.t('netzke.basepack.grid_panel.actions.edit_in_form'),
260
294
  :disabled => true,
261
295
  :icon => :application_form_edit
262
296
  }
263
297
 
264
298
  action :search, {
265
- :text => I18n.t('netzke.basepack.grid_panel.search', :default => "Search"),
266
- :tooltip => I18n.t('netzke.basepack.grid_panel.search', :default => "Search"),
299
+ :text => I18n.t('netzke.basepack.grid_panel.actions.search'),
300
+ :tooltip => I18n.t('netzke.basepack.grid_panel.actions.search'),
267
301
  :enable_toggle => true,
268
302
  :icon => :find
269
303
  }
@@ -271,13 +305,13 @@ module Netzke
271
305
  component :add_form do
272
306
  {
273
307
  :lazy_loading => true,
274
- :class_name => "Basepack::GridPanel::RecordFormWindow",
275
- :title => "Add #{data_class.table_name.singularize.humanize}",
308
+ :class_name => "Netzke::Basepack::GridPanel::RecordFormWindow",
309
+ :title => "Add #{data_class.model_name.human}",
276
310
  :button_align => "right",
277
311
  :items => [{
278
- :class_name => "Basepack::FormPanel",
312
+ :class_name => "Netzke::Basepack::FormPanel",
279
313
  :model => config[:model],
280
- :items => default_fields_for_forms,
314
+ :items => default_fields_for_forms_with_default_values,
281
315
  :persistent_config => config[:persistent_config],
282
316
  :strong_default_attrs => config[:strong_default_attrs],
283
317
  :border => true,
@@ -292,11 +326,11 @@ module Netzke
292
326
  component :edit_form do
293
327
  {
294
328
  :lazy_loading => true,
295
- :class_name => "Basepack::GridPanel::RecordFormWindow",
296
- :title => "Edit #{data_class.table_name.singularize.humanize}",
329
+ :class_name => "Netzke::Basepack::GridPanel::RecordFormWindow",
330
+ :title => "Edit #{data_class.model_name.human}",
297
331
  :button_align => "right",
298
332
  :items => [{
299
- :class_name => "Basepack::FormPanel",
333
+ :class_name => "Netzke::Basepack::FormPanel",
300
334
  :model => config[:model],
301
335
  :items => default_fields_for_forms,
302
336
  :persistent_config => config[:persistent_config],
@@ -311,11 +345,11 @@ module Netzke
311
345
  component :multi_edit_form do
312
346
  {
313
347
  :lazy_loading => true,
314
- :class_name => "Basepack::GridPanel::RecordFormWindow",
315
- :title => "Edit #{data_class.table_name.humanize}",
348
+ :class_name => "Netzke::Basepack::GridPanel::RecordFormWindow",
349
+ :title => "Edit #{data_class.model_name.human.pluralize}",
316
350
  :button_align => "right",
317
351
  :items => [{
318
- :class_name => "Basepack::GridPanel::MultiEditForm",
352
+ :class_name => "Netzke::Basepack::GridPanel::MultiEditForm",
319
353
  :model => config[:model],
320
354
  :items => default_fields_for_forms,
321
355
  :persistent_config => config[:persistent_config],
@@ -329,7 +363,7 @@ module Netzke
329
363
  component :search_form do
330
364
  {
331
365
  :lazy_loading => true,
332
- :class_name => "Basepack::GridPanel::SearchWindow",
366
+ :class_name => "Netzke::Basepack::GridPanel::SearchWindow",
333
367
  :model => config[:model],
334
368
  :fields => default_fields_for_forms
335
369
  }
@@ -338,7 +372,7 @@ module Netzke
338
372
 
339
373
  # def search_panel
340
374
  # {
341
- # :class_name => "Basepack::FormPanel",
375
+ # :class_name => "Netzke::Basepack::FormPanel",
342
376
  # :model => "User",
343
377
  # # :items => default_fields_for_forms,
344
378
  # # :search_class_name => cronfig[:model],
@@ -353,4 +387,4 @@ module Netzke
353
387
 
354
388
  end
355
389
  end
356
- end
390
+ end
@@ -66,6 +66,11 @@ module Netzke
66
66
  end
67
67
  end
68
68
 
69
+ # Columns as a hash, for easier access to a specific column
70
+ def columns_hash
71
+ @columns_hash ||= columns.inject({}){|r,c| r.merge(c[:name].to_sym => c)}
72
+ end
73
+
69
74
  # Columns that we fall back to when neither persistent columns, nor configured columns are present.
70
75
  # If there's a model-level field configuration, it's being used.
71
76
  # Otherwise the defaults straight from the ActiveRecord model ("netzke_attributes").
@@ -101,6 +106,7 @@ module Netzke
101
106
  # Make the column config complete with the defaults
102
107
  columns_for_create.each do |c|
103
108
  detect_association(c)
109
+ set_default_virtual(c)
104
110
  set_default_header(c)
105
111
  set_default_editor(c)
106
112
  set_default_width(c)
@@ -114,6 +120,7 @@ module Netzke
114
120
  end
115
121
 
116
122
  private
123
+
117
124
  def filter_out_excluded_columns(cols)
118
125
  cols.reject!{ |c| c[:included] == false }
119
126
  end
@@ -132,7 +139,7 @@ module Netzke
132
139
  end
133
140
 
134
141
  def set_default_header(c)
135
- c[:label] ||= c[:name].humanize
142
+ c[:label] ||= data_class.human_attribute_name(c[:name])
136
143
  end
137
144
 
138
145
  def set_default_editor(c)
@@ -150,8 +157,15 @@ module Netzke
150
157
  end
151
158
 
152
159
  def set_default_editable(c)
153
- c[:editable] = c[:read_only].nil? ? !(primary_key_attr?(c) || c[:virtual]) : !c[:read_only]
154
- c.delete(:read_only)
160
+ not_editable_if = primary_key_attr?(c)
161
+ not_editable_if ||= c[:virtual]
162
+ not_editable_if ||= c.delete(:read_only)
163
+
164
+ editable_if = data_class.column_names.include?(c[:name])
165
+ editable_if ||= data_class.instance_methods.map(&:to_s).include?("#{c[:name]}=")
166
+ editable_if ||= association_attr?(c[:name])
167
+
168
+ c[:editable] = editable_if && !not_editable_if if c[:editable].nil?
155
169
  end
156
170
 
157
171
  def set_default_sortable(c)
@@ -164,7 +178,7 @@ module Netzke
164
178
 
165
179
  # Returns editor's xtype for a column type
166
180
  def editor_for_attr_type(type)
167
- attr_type_to_editor_map[type]
181
+ attr_type_to_editor_map[type] || :textfield
168
182
  end
169
183
 
170
184
  def editor_for_association
@@ -185,23 +199,34 @@ module Netzke
185
199
 
186
200
  # Detects an association column and sets up the proper editor.
187
201
  def detect_association(c)
188
- # double-underscore notation? surely an association column
189
- if c[:name].index('__')
190
- assoc_name, assoc_method = c[:name].split('__')
191
- if assoc_method && assoc = data_class.reflect_on_association(assoc_name.to_sym)
192
- assoc_column = assoc.klass.columns_hash[assoc_method]
193
- assoc_method_type = assoc_column.try(:type)
194
-
195
- # if association column is boolean, display a checkbox (or alike), otherwise - a combobox (or alike)
202
+ assoc, assoc_method = get_assoc_and_method(c)
203
+ if assoc
204
+ assoc_column = assoc.klass.columns_hash[assoc_method]
205
+ assoc_method_type = assoc_column.try(:type)
206
+
207
+ # if association column is boolean, display a checkbox (or alike), otherwise - a combobox (or alike)
208
+ if c[:nested_attribute]
209
+ c[:editor] ||= editor_for_attr_type(assoc_method_type)
210
+ else
196
211
  c[:editor] ||= assoc_method_type == :boolean ? editor_for_attr_type(:boolean) : editor_for_association
197
212
  end
198
213
  end
199
214
  end
200
215
 
216
+ def get_assoc_and_method(c)
217
+ if c[:name].index("__")
218
+ assoc_name, assoc_method = c[:name].split('__')
219
+ assoc = data_class.reflect_on_association(assoc_name.to_sym)
220
+ [assoc, assoc_method]
221
+ else
222
+ [nil, nil]
223
+ end
224
+ end
225
+
201
226
  # Default fields that will be displayed in the Add/Edit/Search forms
227
+ # When overriding this method, keep in mind that the fields inside the layout must be expanded (each field represented by a hash, not just a symbol)
202
228
  def default_fields_for_forms
203
- form_klass = "Netzke::ModelExtensions::#{config[:model]}ForFormPanel".constantize rescue nil
204
- form_klass ||= original_data_class
229
+ form_klass = constantize_class_name("Netzke::ModelExtensions::#{config[:model]}ForFormPanel") || original_data_class
205
230
 
206
231
  # Select only those fields that are known to the form_klass
207
232
  selected_columns = columns.select do |c|
@@ -220,6 +245,26 @@ module Netzke
220
245
  end
221
246
  end
222
247
 
248
+ # default_fields_for_forms extended with default values (for new-record form)
249
+ def default_fields_for_forms_with_default_values
250
+ res = default_fields_for_forms.dup
251
+ each_attr_in(res) do |a|
252
+ attr_name = a[:name].to_sym
253
+ a[:value] = a[:default_value] || columns_hash[attr_name].try(:fetch, :default_value, nil) || data_class.netzke_attribute_hash[attr_name].try(:fetch, :default_value, nil)
254
+ end
255
+ res
256
+ end
257
+
258
+ # Recursively traversess items (an array) and yields each found field (a hash with :name set)
259
+ def each_attr_in(items)
260
+ items.each do |item|
261
+ if item.is_a?(Hash)
262
+ each_attr_in(item[:items]) if item[:items].is_a?(Array)
263
+ yield(item) if item[:name]
264
+ end
265
+ end
266
+ end
267
+
223
268
  # Receives 2 arrays of columns. Merges the missing config from the +source+ into +dest+, matching columns by name
224
269
  def reverse_merge_equally_named_columns(dest, source)
225
270
  dest.each{ |dc| dc.reverse_merge!(source.detect{ |sc| sc[:name] == dc[:name] } || {}) }
@@ -228,4 +273,4 @@ module Netzke
228
273
  end
229
274
  end
230
275
  end
231
- end
276
+ end
@@ -1,4 +1,4 @@
1
- Ext.override(Netzke.pre.GridPanel, {
1
+ {
2
2
  onSearch: function(el){
3
3
  el.toggle(el.toggled); // do not toggle immediately
4
4
 
@@ -30,67 +30,5 @@ Ext.override(Netzke.pre.GridPanel, {
30
30
  }
31
31
  }, this);
32
32
  }, scope: this});
33
-
34
- // delete this.searchWindow;
35
- // this.searchWindow = new Ext.Window({
36
- // title:'Advanced search',
37
- // layout:'fit',
38
- // modal: true,
39
- // width: 400,
40
- // height: Ext.lib.Dom.getViewHeight() *0.9,
41
- // closeAction:'close',
42
- // buttons:[{
43
- // text: 'OK',
44
- // handler: function(){
45
- // this.ownerCt.ownerCt.closePositively();
46
- // }
47
- // },{
48
- // text:'Cancel',
49
- // handler:function(){
50
- // this.ownerCt.ownerCt.closeNegatively();
51
- // }
52
- // }],
53
- // closePositively : function(){
54
- // this.conditions = this.getNetzkeComponent().getForm().getValues();
55
- // this.closeRes = 'OK';
56
- // this.close();
57
- // },
58
- // closeNegatively: function(){
59
- // this.closeRes = 'cancel';
60
- // this.close();
61
- // }
62
- // });
63
- //
64
- // this.searchWindow.on('close', function(){
65
- // if (this.searchWindow.closeRes == 'OK'){
66
- // var searchConditions = this.searchWindow.conditions;
67
- // var filtered = false;
68
- // // check if there's any search condition set
69
- // for (var k in searchConditions) {
70
- // if (searchConditions[k].length > 0) {
71
- // filtered = true;
72
- // break;
73
- // }
74
- // }
75
- // this.actions.search.setText(filtered ? "Search *" : "Search");
76
- // this.getStore().baseParams = {extra_conditions: Ext.encode(this.searchWindow.conditions)};
77
- // this.getStore().load();
78
- // }
79
- // }, this);
80
- //
81
- // this.searchWindow.on('add', function(container, searchPanel){
82
- // searchPanel.on('apply', function(component){
83
- // this.searchWindow.closePositively();
84
- // return false; // stop the event
85
- // }, this);
86
- // }, this);
87
- //
88
- // this.searchWindow.show(null, function(){
89
- // this.searchWindow.closeRes = 'cancel';
90
- // if (!this.searchWindow.getNetzkeComponent()){
91
- // this.loadComponent({id:"searchPanel", container:this.searchWindow.id});
92
- // }
93
- // }, this);
94
- //
95
33
  }
96
- });
34
+ }