netzke-basepack 0.5.8 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/CHANGELOG.rdoc +18 -0
  2. data/README.rdoc +11 -4
  3. data/Rakefile +19 -3
  4. data/TODO.rdoc +1 -1
  5. data/generators/netzke_basepack/netzke_basepack_generator.rb +13 -0
  6. data/generators/netzke_basepack/templates/create_netzke_field_lists.rb +18 -0
  7. data/generators/netzke_basepack/templates/public_assets/ts-checkbox.gif +0 -0
  8. data/install.rb +1 -1
  9. data/javascripts/basepack.js +124 -30
  10. data/lib/app/models/netzke_field_list.rb +261 -0
  11. data/lib/app/models/netzke_model_attr_list.rb +21 -0
  12. data/lib/app/models/netzke_persistent_array_auto_model.rb +58 -0
  13. data/lib/netzke-basepack.rb +17 -2
  14. data/lib/netzke/active_record.rb +10 -0
  15. data/lib/netzke/active_record/association_attributes.rb +102 -0
  16. data/lib/netzke/active_record/attributes.rb +100 -0
  17. data/lib/netzke/active_record/combobox_options.rb +43 -0
  18. data/lib/netzke/active_record/data_accessor.rb +9 -12
  19. data/lib/netzke/attributes_configurator.rb +195 -0
  20. data/lib/netzke/basic_app.rb +47 -4
  21. data/lib/netzke/configuration_panel.rb +1 -1
  22. data/lib/netzke/data_accessor.rb +7 -30
  23. data/lib/netzke/fields_configurator.rb +106 -41
  24. data/lib/netzke/form_panel.rb +28 -125
  25. data/lib/netzke/form_panel/form_panel_api.rb +2 -3
  26. data/lib/netzke/form_panel/form_panel_fields.rb +147 -0
  27. data/lib/netzke/form_panel/form_panel_js.rb +35 -15
  28. data/lib/netzke/grid_panel.rb +130 -213
  29. data/lib/netzke/grid_panel/grid_panel_api.rb +254 -257
  30. data/lib/netzke/grid_panel/grid_panel_columns.rb +226 -0
  31. data/lib/netzke/grid_panel/grid_panel_js.rb +126 -119
  32. data/lib/netzke/grid_panel/record_form_window.rb +7 -1
  33. data/lib/netzke/json_array_editor.rb +61 -0
  34. data/lib/netzke/plugins/configuration_tool.rb +1 -1
  35. data/lib/netzke/property_editor.rb +3 -3
  36. data/lib/netzke/search_panel.rb +164 -27
  37. data/lib/netzke/tab_panel.rb +14 -12
  38. data/stylesheets/basepack.css +43 -2
  39. data/test/app_root/app/models/book.rb +1 -1
  40. data/test/app_root/app/models/role.rb +3 -0
  41. data/test/app_root/app/models/user.rb +3 -0
  42. data/test/app_root/config/database.yml +1 -1
  43. data/test/app_root/db/migrate/20090102223630_create_netzke_field_lists.rb +18 -0
  44. data/test/app_root/db/migrate/20090423214303_create_roles.rb +11 -0
  45. data/test/app_root/db/migrate/20090423222114_create_users.rb +12 -0
  46. data/test/fixtures/books.yml +4 -2
  47. data/test/fixtures/categories.yml +2 -2
  48. data/test/fixtures/genres.yml +6 -6
  49. data/test/fixtures/roles.yml +8 -0
  50. data/test/fixtures/users.yml +11 -0
  51. data/test/test_helper.rb +2 -0
  52. data/test/unit/active_record_basepack_test.rb +2 -2
  53. data/test/unit/fields_configuration_test.rb +18 -0
  54. data/test/unit/grid_panel_test.rb +29 -27
  55. metadata +41 -16
  56. data/lib/app/models/netzke_auto_column.rb +0 -4
  57. data/lib/app/models/netzke_auto_field.rb +0 -4
  58. data/lib/app/models/netzke_auto_table.rb +0 -61
  59. data/lib/netzke/active_record/basepack.rb +0 -134
  60. data/lib/netzke/grid_panel/javascripts/filters.js +0 -7
  61. data/test/app_root/db/migrate/20090102223630_create_netzke_layouts.rb +0 -14
  62. data/test/unit/helper_model_test.rb +0 -30
@@ -182,6 +182,42 @@ module Netzke
182
182
  }
183
183
  END_OF_JAVASCRIPT
184
184
 
185
+ # NOT USED
186
+ :show_login_window => <<-END_OF_JAVASCRIPT.l,
187
+ function(){
188
+ var w = new Ext.Window({
189
+ title: "Please, login",
190
+ modal: true,
191
+ width: 350,
192
+ height: 200,
193
+ layout: 'fit',
194
+ items: [{
195
+ xtype: 'form',
196
+ padding: 20,
197
+ defaults: {anchor: '100%'},
198
+ frame: true,
199
+ border: false,
200
+ items: [
201
+ {xtype: 'textfield', fieldLabel: 'Username', name: 'login'},
202
+ {name: 'password', xtype: 'textfield', inputType: 'password', fieldLabel: "Password"}
203
+ ],
204
+ buttons: [{
205
+ name: "submit",
206
+ text: "Login",
207
+ app: this,
208
+ handler: function() {
209
+ this.ownerCt.ownerCt.getForm().submit({
210
+ url: this.app.buildApiUrl("submit_login"),
211
+ });
212
+ }
213
+ }]
214
+ }],
215
+ });
216
+
217
+ w.show();
218
+ }
219
+ END_OF_JAVASCRIPT
220
+
185
221
 
186
222
  # Masquerade selector window
187
223
  :show_masquerade_selector => <<-END_OF_JAVASCRIPT.l
@@ -315,10 +351,17 @@ module Netzke
315
351
  api :masquerade_as
316
352
  def masquerade_as(params)
317
353
  session = Netzke::Base.session
318
- session[:masq_world] = params[:world]
319
- session[:masq_role] = params[:role]
320
- session[:masq_user] = params[:user]
321
- {:js => "window.location.reload()"}
354
+ session[:masq_world] = params[:world] == "true"
355
+ session[:masq_role] = params[:role].try(:to_i)
356
+ session[:masq_user] = params[:user].try(:to_i)
357
+ {:js => "window.location.reload();"}
358
+ end
359
+
360
+ # Login request from the in-app login form
361
+ api :submit_login
362
+ def submit_login(params)
363
+ # TODO: implement me
364
+ {:feedback => "OK"}
322
365
  end
323
366
 
324
367
  end
@@ -6,7 +6,7 @@ module Netzke
6
6
  def commit(params)
7
7
  commit_data = ActiveSupport::JSON.decode params[:commit_data]
8
8
  commit_data.each_pair do |k,v|
9
- aggregatee_instance(k).commit(v)
9
+ aggregatee_instance(k).commit(v) if aggregatee_instance(k).respond_to?(:commit)
10
10
  end
11
11
  {:reload_parent => true, :feedback => (@flash.empty? ? nil : @flash)}
12
12
  end
@@ -14,38 +14,15 @@ module Netzke
14
14
  # Generic extensions to the data model
15
15
  if data_class # because some widgets, like FormPanel, may have it optional
16
16
  data_class.send(:include, Netzke::ActiveRecord::DataAccessor) if !data_class.include?(Netzke::ActiveRecord::DataAccessor)
17
-
18
- # Model helpers
19
- const_name = "Netzke::Helpers::#{data_class.name}"
20
- model_extensions = const_name.constantize rescue nil
21
- data_class.send(:include, model_extensions) if model_extensions && !data_class.include?(model_extensions)
22
17
  end
23
18
  end
24
-
25
- # Returns columns that are exposed by the class and the helpers
26
- def predefined_columns
27
- helper_module = "Netzke::Helpers::#{short_widget_class_name}#{data_class.name}".constantize rescue nil
28
-
29
- data_class_columns = data_class && data_class.column_names.map(&:to_sym) || []
30
-
31
- if helper_module
32
- exposed_attributes = helper_module.respond_to?(:exposed_attributes) ? normalize_array_of_columns(helper_module.exposed_attributes) : nil
33
- virtual_attributes = helper_module.respond_to?(:virtual_attributes) ? helper_module.virtual_attributes : []
34
- excluded_attributes = helper_module.respond_to?(:excluded_attributes) ? helper_module.excluded_attributes : []
35
- attributes_config = helper_module.respond_to?(:attributes_config) ? helper_module.attributes_config : {}
36
-
37
- res = exposed_attributes || data_class_columns + virtual_attributes
38
-
39
- res = normalize_columns(res)
40
-
41
- res.reject!{ |c| excluded_attributes.include? c[:name] }
42
-
43
- res.map!{ |c| c.merge!(attributes_config[c[:name]] || {})}
44
- else
45
- res = normalize_columns(data_class_columns)
19
+
20
+ # [:col1, "col2", {:name => :col3}] =>
21
+ # [{:name => "col1"}, {:name => "col2"}, {:name => "col3"}]
22
+ def normalize_attr_config(cols)
23
+ cols.map do |c|
24
+ c.is_a?(Symbol) || c.is_a?(String) ? {:name => c.to_s} : c.merge(:name => c[:name].to_s)
46
25
  end
47
-
48
- res
49
26
  end
50
27
 
51
28
  # Make sure we have keys as symbols, not strings
@@ -61,7 +38,7 @@ module Netzke
61
38
 
62
39
  # From symbol to config hash
63
40
  def normalize_column(field)
64
- field.is_a?(Symbol) ? {:name => field} : field
41
+ field.is_a?(Symbol) ? {:name => field.to_s} : field
65
42
  end
66
43
 
67
44
  # From symbols to config hashes
@@ -3,42 +3,26 @@ module Netzke
3
3
  # Provides dynamic configuring columns/fields for GridPanel and FormPanel.
4
4
  # Configuration parameters:
5
5
  # * <tt>:widget</tt> - widget to configure columns/fields for
6
- class FieldsConfigurator < GridPanel
6
+ class FieldsConfigurator < JsonArrayEditor
7
7
  api :load_defaults
8
8
 
9
- def initialize(*args)
10
- super
11
- @auto_table_klass = is_for_grid? ? NetzkeAutoColumn : NetzkeAutoField
12
- @auto_table_klass.widget = client_widget
13
- end
14
-
15
- # widget that uses us
16
- def client_widget
17
- @passed_config[:widget]
18
- end
19
-
20
- # is our client widget a grid (as opposed to a form)?
21
- def is_for_grid?
22
- client_widget.class.ancestors.include?(GridPanel)
23
- end
24
-
25
9
  def default_config
26
10
  super.deep_merge({
27
11
  :name => 'columns',
28
- :model => is_for_grid? ? "NetzkeAutoColumn" : "NetzkeAutoField",
29
12
  :ext_config => {
13
+ :config_tool => false,
30
14
  :header => false,
31
15
  :enable_extended_search => false,
32
16
  :enable_edit_in_form => false,
33
17
  :enable_rows_reordering => GridPanel.config[:rows_reordering_available],
34
18
  :enable_pagination => false
35
- },
19
+ }
36
20
  })
37
21
  end
38
22
 
39
23
  def actions
40
24
  super.merge(
41
- :defaults => {:text => 'Restore defaults'}
25
+ :defaults => {:text => 'Restore defaults', :icon => Netzke::Base.config[:with_icons] && (Netzke::Base.config[:icons_uri] + "wand.png")}
42
26
  )
43
27
  end
44
28
 
@@ -46,12 +30,52 @@ module Netzke
46
30
  %w{ add edit apply del - defaults }
47
31
  end
48
32
 
49
- def predefined_columns
50
- [{:name => :id}, *config[:widget].class.config_columns]
33
+ # Default columns for the configurator
34
+ def default_columns
35
+ [
36
+ {:name => "id", :attr_type => :integer, :meta => true},
37
+ {:name => "position", :attr_type => :integer, :meta => true},
38
+ {:name => "attr_type", :attr_type => :string, :meta => true},
39
+ *config[:owner].class.meta_columns.map { |c| c[:name] == "name" ? inject_combo_for_name_column(c) : c }
40
+ ]
51
41
  end
52
42
 
53
43
  def self.js_extend_properties
54
44
  {
45
+ :init_component => <<-END_OF_JAVASCRIPT.l,
46
+ function(){
47
+ #{js_full_class_name}.superclass.initComponent.call(this);
48
+
49
+ // Automatically set the correct editor for the default_value column
50
+ this.on('beforeedit', function(e){
51
+ var column = this.getColumnModel().getColumnById(this.getColumnModel().getColumnId(e.column));
52
+ var record = this.getStore().getAt(e.row);
53
+
54
+ if (column.dataIndex === "default_value") {
55
+ if (record.get("name") === this.pri) {
56
+ // Don't allow setting default value for the primary key
57
+ column.setEditor(null);
58
+ } else {
59
+ // Auto set the editor, dependent on the field type
60
+ var attrType = record.get("attr_type");
61
+ column.setEditor(Ext.create({xtype: this.attrTypeEditorMap[attrType] || "textfield"}));
62
+ }
63
+ }
64
+
65
+ }, this);
66
+
67
+ }
68
+ END_OF_JAVASCRIPT
69
+
70
+ :attr_type_editor_map => {
71
+ :integer => "numberfield",
72
+ :boolean => "checkbox",
73
+ :decimal => "numberfield",
74
+ :datetime => "xdatetime",
75
+ :date => "datefield",
76
+ :string => "textfield"
77
+ },
78
+
55
79
  # Disable the 'gear' tool for now
56
80
  :on_gear => <<-END_OF_JAVASCRIPT.l,
57
81
  function(){
@@ -79,31 +103,72 @@ module Netzke
79
103
  end
80
104
 
81
105
  def load_defaults(params)
82
- config[:widget].persistent_config[:layout__columns] = config[:widget].default_columns
83
- @auto_table_klass.rebuild_table
106
+ # Reload the temp table with default values
107
+ data_class.replace_data(default_owner_fields)
108
+
109
+ # ... and reflect it in the persistent storage
110
+ on_data_changed
111
+
112
+ # Update the grid
84
113
  {:load_store_data => get_data}
85
114
  end
86
115
 
87
- def commit(params)
88
- defaults_hash = config[:widget].class.config_columns.inject({}){ |r, c| r.merge!(c[:name] => c[:default]) }
89
- config[:widget].persistent_config[:layout__columns] = @auto_table_klass.all_columns.map do |c|
90
- # reject all keys that are 1) same as defaults, 2) 'position'
91
- c.reject!{ |k,v| defaults_hash[k.to_sym].to_s == v.to_s || k == 'position'}
92
- c = c["name"] if c.keys.count == 1 # denormalize the column
93
- c
94
- end
95
- {}
96
- end
97
-
98
- # each time that we are loaded into the app, rebuild the table
99
- def before_load
100
- @auto_table_klass.rebuild_table
101
- end
102
-
103
- # Don't show the config tool
116
+ # Never show the config tool
104
117
  def config_tool_needed?
105
118
  false
106
119
  end
107
120
 
121
+ private
122
+
123
+ # An override
124
+ def process_data(data, operation)
125
+ if operation == :update
126
+ meta_attrs_to_update = data.inject({}) do |r,el|
127
+ r.merge({
128
+ data_class.find(el["id"]).name => el.reject{ |k,v| k == "id" }
129
+ })
130
+ end
131
+
132
+ res = super
133
+
134
+ NetzkeFieldList.update_fields(config[:owner].global_id, meta_attrs_to_update)
135
+
136
+ res
137
+ else
138
+ super
139
+ end
140
+ end
141
+
142
+ # An override
143
+ def store_data(data)
144
+ NetzkeFieldList.update_list_for_current_authority(config[:owner].global_id, data, config[:owner].data_class.name)
145
+ end
146
+
147
+ # An override
148
+ def initial_data
149
+ NetzkeFieldList.read_list(config[:owner].global_id) || default_owner_fields
150
+ end
151
+
152
+ # Set strict combo for the "name" column, with options of the attributes provided by the data_class
153
+ def inject_combo_for_name_column(c)
154
+ netzke_attrs = config[:owner].data_class.netzke_attributes.map{ |a| a[:name] }
155
+ c.merge(:editor => {:xtype => :combo, :store => netzke_attrs, :force_selection => true})
156
+ end
157
+
158
+ def default_owner_fields
159
+ config[:owner].initial_columns(false).map(&:deebeefy_values)
160
+ end
161
+
162
+ # This is an override of GridPanel#on_data_changed
163
+ def on_data_changed
164
+ # Default column settings taken from
165
+ defaults_hash = config[:owner].class.meta_columns.inject({}){ |r, c| r.merge!(c[:name] => c[:default_value]) }
166
+ stripped_columns = data_class.all_columns.map do |c|
167
+ # reject all keys that are 1) same as defaults
168
+ c.reject{ |k,v| defaults_hash[k.to_sym].to_s == v.to_s }
169
+ end
170
+ store_data(stripped_columns)
171
+ end
172
+
108
173
  end
109
174
  end
@@ -1,5 +1,6 @@
1
1
  require "netzke/form_panel/form_panel_js"
2
2
  require "netzke/form_panel/form_panel_api"
3
+ require "netzke/form_panel/form_panel_fields"
3
4
  require "netzke/plugins/configuration_tool"
4
5
  require "netzke/data_accessor"
5
6
 
@@ -19,6 +20,7 @@ module Netzke
19
20
  class FormPanel < Base
20
21
  include FormPanelJs # javascript (client-side)
21
22
  include FormPanelApi # API (server-side)
23
+ include FormPanelFields # fields
22
24
  include Netzke::DataAccessor # some code shared between GridPanel, FormPanel, and other widgets that use database attributes
23
25
 
24
26
  # Class-level configuration with defaults
@@ -61,14 +63,22 @@ module Netzke
61
63
  def initialize(*args)
62
64
  super
63
65
  apply_helpers
64
- @record = config[:record] || config[:record_id] && data_class && data_class.find(:first, :conditions => {data_class.primary_key => config[:record_id]})
65
66
  end
66
67
 
67
68
  # (We can't memoize this method because at some point we extend it, e.g. in Netzke::DataAccessor)
68
69
  def data_class
69
- ::ActiveSupport::Deprecation.warn("data_class_name option is deprecated. Use model instead", caller) if config[:data_class_name]
70
- model_name = config[:model] || config[:data_class_name]
71
- @data_class ||= model_name && model_name.constantize
70
+ @data_class ||= begin
71
+ klass = "Netzke::ModelExtensions::#{config[:model]}For#{short_widget_class_name}".constantize rescue nil
72
+ klass || begin
73
+ ::ActiveSupport::Deprecation.warn("data_class_name option is deprecated. Use model instead", caller) if config[:data_class_name]
74
+ model_name = config[:model] || config[:data_class_name]
75
+ model_name && model_name.constantize
76
+ end
77
+ end
78
+ end
79
+
80
+ def record
81
+ @record ||= config[:record] || config[:record_id] && data_class && data_class.find(:first, :conditions => {data_class.primary_key => config[:record_id]})
72
82
  end
73
83
 
74
84
  def configuration_widgets
@@ -78,7 +88,7 @@ module Netzke
78
88
  :name => 'fields',
79
89
  :class_name => "FieldsConfigurator",
80
90
  :active => true,
81
- :widget => self,
91
+ :owner => self,
82
92
  :persistent_config => true
83
93
  }
84
94
 
@@ -93,137 +103,30 @@ module Netzke
93
103
  end
94
104
 
95
105
  def actions
96
- {
106
+ actions = {
97
107
  :apply => {:text => 'Apply'}
98
108
  }
109
+
110
+ if Netzke::Base.config[:with_icons]
111
+ icons_uri = Netzke::Base.config[:icons_uri]
112
+ actions.deep_merge!(
113
+ :apply => {:icon => icons_uri + "tick.png"}
114
+ )
115
+ end
116
+
117
+ actions
99
118
  end
100
119
 
101
- def columns
102
- @columns ||= get_columns.deep_convert_keys{|k| k.to_sym}
103
- end
104
-
105
- # parameters used to instantiate the JS object
106
- def js_config
107
- res = super
108
- res.merge!(:clmns => columns)
109
- res.merge!(:model => data_class.name) if data_class
110
- res.merge!(:pri => data_class.primary_key) if data_class
111
- res
112
- end
113
-
114
- # columns to be displayed by the FieldConfigurator (which is GridPanel-based)
115
- def self.config_columns
116
- [
117
- {:name => :name, :type => :string, :editor => :combobox, :width => 200},
118
- {:name => :hidden, :type => :boolean, :editor => :checkbox, :width => 40, :header => "Excl"},
119
- {:name => :disabled, :type => :boolean, :editor => :checkbox, :width => 40, :header => "Dis"},
120
- {:name => :xtype, :type => :string, :editor => {:xtype => :combobox, :options => Netzke::Ext::FORM_FIELD_XTYPES}},
121
- {:name => :value, :type => :string},
122
- {:name => :field_label, :type => :string},
123
- {:name => :input_type, :type => :string, :hidden => true}
124
- ]
125
- end
126
-
127
120
  def self.property_fields
128
121
  res = [
129
- {:name => :ext_config__title, :type => :string},
130
- {:name => :ext_config__header, :type => :boolean, :default => true},
131
- {:name => :ext_config__bbar, :type => :json}
122
+ {:name => "ext_config__title", :type => :string},
123
+ {:name => "ext_config__header", :type => :boolean, :default => true},
124
+ # {:name => "ext_config__bbar", :type => :json}
132
125
  ]
133
126
 
134
127
  res
135
128
  end
136
129
 
137
- # Normalized columns
138
- def normalized_columns
139
- @normalized_columns ||= normalize_columns(columns)
140
- end
141
-
142
-
143
- def get_columns
144
- if persistent_config_enabled?
145
- persistent_config['layout__columns'] ||= default_columns
146
- res = normalize_array_of_columns(persistent_config['layout__columns'])
147
- else
148
- res = default_columns
149
- end
150
-
151
- # merge values for each field if the record is specified
152
- @record && res.map! do |c|
153
- value = @record.send(normalize_column(c)[:name])
154
- value.nil? ? c : normalize_column(c).merge(:value => value)
155
- end
156
-
157
- res
158
- end
159
-
160
- XTYPE_MAP = {
161
- :integer => :numberfield,
162
- :boolean => :xcheckbox,
163
- :date => :datefield,
164
- :datetime => :xdatetime,
165
- :text => :textarea,
166
- :json => :jsonfield
167
- # :string => :textfield
168
- }
169
-
170
- def default_columns
171
- # columns specified in widget's config
172
- columns_from_config = config[:columns] && normalize_columns(config[:columns])
173
-
174
- if columns_from_config
175
- # reverse-merge each column hash from config with each column hash from exposed_attributes (columns from config have higher priority)
176
- for c in columns_from_config
177
- corresponding_exposed_column = predefined_columns.find{ |k| k[:name] == c[:name] }
178
- c.reverse_merge!(corresponding_exposed_column) if corresponding_exposed_column
179
- end
180
- columns_for_create = columns_from_config
181
- elsif predefined_columns
182
- # we didn't have columns configured in widget's config, so, use the columns from the data class
183
- columns_for_create = predefined_columns
184
- else
185
- raise ArgumentError, "No columns specified for widget '#{global_id}'"
186
- end
187
-
188
- columns_for_create.map! do |c|
189
- if data_class
190
- # Try to figure out the configuration from data class
191
- # detect :assoc__method
192
- if c[:name].to_s.index('__')
193
- assoc_name, method = c[:name].to_s.split('__').map(&:to_sym)
194
- if assoc = data_class.reflect_on_association(assoc_name)
195
- assoc_column = assoc.klass.columns_hash[method.to_s]
196
- assoc_method_type = assoc_column.try(:type)
197
- if assoc_method_type
198
- c[:xtype] ||= XTYPE_MAP[assoc_method_type] == :xcheckbox ? :xcheckbox : :combobox
199
- end
200
- end
201
- end
202
-
203
- # detect association column (e.g. :category_id)
204
- if assoc = data_class.reflect_on_all_associations.detect{|a| a.primary_key_name.to_sym == c[:name]}
205
- c[:xtype] ||= :combobox
206
- assoc_method = %w{name title label id}.detect{|m| (assoc.klass.instance_methods + assoc.klass.column_names).include?(m) } || assoc.klass.primary_key
207
- c[:name] = "#{assoc.name}__#{assoc_method}".to_sym
208
- end
209
- c[:hidden] = true if c[:name] == data_class.primary_key.to_sym && c[:hidden].nil? # hide ID column by default
210
-
211
- end
212
-
213
- # detect column type
214
- type = c[:type] || data_class && data_class.columns_hash[c[:name].to_s].try(:type) || :string
215
- c[:type] ||= type
216
-
217
- c[:xtype] ||= XTYPE_MAP[type] unless XTYPE_MAP[type].nil?
218
-
219
- # if the column is finally simply {:name => "something"}, cut it down to "something"
220
- c.reject{ |k,v| k == :name }.empty? ? c[:name] : c
221
- end
222
-
223
- columns_for_create
224
-
225
- end
226
-
227
130
  include Plugins::ConfigurationTool if config[:config_tool_available] # it will load ConfigurationPanel into a modal window
228
131
  end
229
132
  end