netzke-basepack 0.3.10 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/CHANGELOG +10 -0
  2. data/Manifest +12 -16
  3. data/Rakefile +1 -1
  4. data/TODO +3 -1
  5. data/autotest/discover.rb +3 -0
  6. data/javascripts/basepack.js +680 -52
  7. data/lib/app/models/netzke_hash_record.rb +180 -0
  8. data/lib/app/models/netzke_layout_item.rb +11 -0
  9. data/lib/netzke/ar_ext.rb +57 -34
  10. data/lib/netzke/border_layout_panel.rb +0 -1
  11. data/lib/netzke/db_fields.rb +4 -0
  12. data/lib/netzke/field_model.rb +131 -0
  13. data/lib/netzke/fields_configurator.rb +13 -5
  14. data/lib/netzke/fields_configurator_old.rb +62 -0
  15. data/lib/netzke/form_panel.rb +18 -24
  16. data/lib/netzke/form_panel_extras/interface.rb +20 -13
  17. data/lib/netzke/form_panel_extras/js_builder.rb +4 -1
  18. data/lib/netzke/grid_panel.rb +37 -40
  19. data/lib/netzke/grid_panel_extras/interface.rb +22 -18
  20. data/lib/netzke/grid_panel_extras/js_builder.rb +42 -13
  21. data/lib/netzke/property_editor_extras/helper_model.rb +2 -1
  22. data/lib/netzke/tab_panel.rb +15 -11
  23. data/netzke-basepack.gemspec +10 -10
  24. data/test/{accordion_panel_test.rb → unit/accordion_panel_test.rb} +0 -0
  25. data/test/{ar_ext_test.rb → unit/ar_ext_test.rb} +3 -9
  26. data/test/{grid_panel_test.rb → unit/grid_panel_test.rb} +0 -5
  27. data/test/{netzke_basepack_test.rb → unit/netzke_basepack_test.rb} +0 -0
  28. data/test/unit/netzke_hash_record_test.rb +52 -0
  29. data/test/unit/netzke_layout_item_test.rb +28 -0
  30. data/test/{tab_panel_test.rb → unit/tab_panel_test.rb} +0 -0
  31. metadata +30 -30
  32. data/generators/netzke_basepack/USAGE +0 -8
  33. data/generators/netzke_basepack/netzke_basepack_generator.rb +0 -8
  34. data/generators/netzke_form_panel/netzke_form_panel_generator.rb +0 -7
  35. data/generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb +0 -21
  36. data/generators/netzke_grid_panel/netzke_grid_panel_generator.rb +0 -7
  37. data/generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb +0 -24
  38. data/lib/app/models/netzke_form_panel_field.rb +0 -51
  39. data/lib/app/models/netzke_grid_panel_column.rb +0 -56
  40. data/lib/netzke/form_panel_extras/javascripts/xdatetime.js +0 -634
  41. data/test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb +0 -23
  42. data/test/border_layout_panel_test.rb +0 -25
@@ -0,0 +1,180 @@
1
+ class NetzkeHashRecord < Hash
2
+ include Netzke::ActiveRecordExtensions
3
+ #
4
+ # Class methods
5
+ #
6
+ def self.widget=(w)
7
+ @@widget = w
8
+ reload
9
+ end
10
+
11
+ def self.widget
12
+ @@widget ||= nil
13
+ raise "No widget specified for NetzkeHashRecord" if @@widget.nil?
14
+ @@widget
15
+ end
16
+
17
+ def self.data=(data)
18
+ @@records = data
19
+ save
20
+ end
21
+
22
+ def self.raw_data=(data)
23
+ persistent_config.for_widget(widget) {|p| p[:layout__columns] = data}
24
+ end
25
+
26
+ def self.columns_hash
27
+ @@columns_hash ||= build_columns_hash
28
+ end
29
+
30
+ def self.push(instance)
31
+ records << instance
32
+ end
33
+
34
+ def self.reload
35
+ @@records = build_records
36
+ end
37
+
38
+ # standard AR operations
39
+ def self.all(params = {})
40
+ records
41
+ end
42
+
43
+ def self.count(params = {})
44
+ records.size
45
+ end
46
+
47
+ def self.find(*args)
48
+ if args.size == 1
49
+ records[args.first.to_i - 1]
50
+ else
51
+ end
52
+ end
53
+
54
+ def self.first
55
+ records.first
56
+ end
57
+
58
+ def self.last
59
+ records.last
60
+ end
61
+
62
+ def self.delete(ids)
63
+ ids.each do |id|
64
+ records.delete_if{|r| r.id == id.to_i}
65
+ end
66
+ recalculate_ids
67
+ save
68
+ end
69
+
70
+ def self.delete_all
71
+ records.clear
72
+ save
73
+ end
74
+
75
+ def self.save
76
+ records_without_ids = records.map{ |r| r.reject{ |k,v| k == :id } }
77
+ persistent_config.for_widget(widget) {|p| p[:layout__columns] = records_without_ids}
78
+ true
79
+ end
80
+
81
+ def self.column_names
82
+ columns_hash.keys.sort{ |x,y| x == "id" ? -1 : 0} # "id"-column should always come first (required by the GridPanel)
83
+ end
84
+
85
+ def self.reflect_on_all_associations
86
+ []
87
+ end
88
+
89
+ #
90
+ # Instance methods
91
+ #
92
+ def initialize(params = {})
93
+ self.replace(params)
94
+ end
95
+
96
+ def id
97
+ self[:id] || self["id"]
98
+ end
99
+
100
+ def id=(id)
101
+ self[:id] = id
102
+ end
103
+
104
+ def save
105
+ if self.id.nil?
106
+ self.id = self.class.records.size + 1
107
+ self.class.push(self)
108
+ else
109
+ # nothing to do
110
+ end
111
+
112
+ self.class.save
113
+ end
114
+
115
+ def errors
116
+ []
117
+ end
118
+
119
+ private
120
+
121
+ def self.persistent_config
122
+ @@persistent_config ||= Netzke::Base.config[:persistent_config_manager].constantize
123
+ end
124
+
125
+ def self.records
126
+ @@records ||= build_records
127
+ end
128
+
129
+ def self.build_records
130
+ raw_records = persistent_config.for_widget(widget){|p| p[:layout__columns]} || []
131
+ records = []
132
+ raw_records.each_with_index do |r,i|
133
+ own_instance = self.new(r.convert_keys{|k| k.to_sym})
134
+ own_instance.merge!(:id => i + 1) # merging with the id
135
+ records << own_instance
136
+ end
137
+ records
138
+ end
139
+
140
+ def self.recalculate_ids
141
+ records.each_with_index { |r, i| r.id = i + 1}
142
+ end
143
+
144
+ def self.build_columns_hash
145
+ res = {}
146
+ records.each do |record|
147
+ record.keys.each do |k|
148
+
149
+ if res[k.to_s].nil?
150
+
151
+ # calculate column type
152
+ column_type = case record[k].class.to_s
153
+ when "TrueClass"
154
+ :boolean
155
+ when "FalseClass"
156
+ :boolean
157
+ when "String"
158
+ :string
159
+ when "Fixnum"
160
+ :integer
161
+ else
162
+ :string
163
+ end
164
+
165
+ column = {:type => column_type}
166
+
167
+ # workaround for the "type" method
168
+ class << column
169
+ def type
170
+ self[:type]
171
+ end
172
+ end
173
+
174
+ res[k.to_s] = column
175
+ end
176
+ end
177
+ end
178
+ res
179
+ end
180
+ end
@@ -0,0 +1,11 @@
1
+ class NetzkeLayoutItem < NetzkeHashRecord
2
+
3
+ # Moving item
4
+ def self.move_item(from, to)
5
+ r = records.delete_at(from)
6
+ records.insert(to, r)
7
+ recalculate_ids
8
+ save
9
+ end
10
+
11
+ end
data/lib/netzke/ar_ext.rb CHANGED
@@ -13,7 +13,7 @@ module Netzke
13
13
  #
14
14
 
15
15
  def method_missing(method, *args, &block)
16
- # if refering to a column, just pass it to the originar method_missing
16
+ # if refering to a column, just pass it to the original method_missing
17
17
  return super if self.class.column_names.include?(method.to_s)
18
18
 
19
19
  split = method.to_s.split(/\.|__/)
@@ -87,7 +87,7 @@ module Netzke
87
87
  else
88
88
  # it's a "virtual" column - the least effective search
89
89
  records = self.find(:all).map{|r| r.send(column)}.uniq
90
- query.nil? ? records : records.select{|r| r.send(column).index(/^#{query}/)}
90
+ query.nil? ? records : records.select{|r| r.index(/^#{query}/)}
91
91
  end
92
92
  end
93
93
  end
@@ -147,16 +147,16 @@ module Netzke
147
147
  assoc_name, method = config[:name].to_s.split('__').map(&:to_sym)
148
148
  if assoc = reflect_on_association(assoc_name)
149
149
  assoc_column = assoc.klass.columns_hash[method.to_s]
150
- assoc_method_type = assoc_column && assoc_column.type
150
+ assoc_method_type = assoc_column.try(:type)
151
151
  if assoc_method_type
152
- res[:editor] = ext_editor(assoc_method_type) == :checkbox ? :checkbox : :combo_box
152
+ res[:editor] = ext_editor(assoc_method_type) == :checkbox ? :checkbox : :combobox
153
153
  end
154
154
  end
155
155
  end
156
156
 
157
157
  # detect association column (e.g. :category_id)
158
158
  if assoc = reflect_on_all_associations.detect{|a| a.primary_key_name.to_sym == config[:name]}
159
- res[:editor] = :combo_box
159
+ res[:editor] = :combobox
160
160
  assoc_method = %w{name title label}.detect{|m| (assoc.klass.instance_methods + assoc.klass.column_names).include?(m) } || assoc.klass.primary_key
161
161
  res[:name] = "#{assoc.name}__#{assoc_method}"
162
162
  end
@@ -174,15 +174,15 @@ module Netzke
174
174
 
175
175
  DEFAULT_COLUMN_WIDTH = 100
176
176
 
177
- # identify Ext editor for the data type
177
+ # identify Ext editor (xtype) for the data type
178
178
  TYPE_EDITOR_MAP = {
179
- :integer => :number_field,
179
+ :integer => :numberfield,
180
180
  :boolean => :checkbox,
181
- :date => :date_field,
182
- :datetime => :datetime,
183
- :string => :text_field
181
+ :date => :datefield,
182
+ :datetime => :xdatetime,
183
+ :string => :textfield
184
184
  }
185
-
185
+
186
186
  # Returns default column config understood by Netzke::GridPanel
187
187
  # Argument: column name (as Symbol) or column config
188
188
  def default_column_config(config)
@@ -194,25 +194,33 @@ module Netzke
194
194
  #
195
195
 
196
196
  # default configuration as a function of ActivRecord's column type
197
- DEFAULTS_FOR_FIELD = {
198
- :integer => {
199
- :xtype => :numberfield
200
- },
201
- :boolean => {
202
- :xtype => :numberfield
203
- },
204
- :date => {
205
- :xtype => :datefield
206
- },
207
- :datetime => {
208
- :xtype => :xdatetime
209
- # :date_format => "Y-m-d",
210
- # :time_format => "H:i",
211
- # :time_width => 60
212
- },
213
- :string => {
214
- :xtype => :textfield
215
- }
197
+ # DEFAULTS_FOR_FIELD = {
198
+ # :integer => {
199
+ # :xtype => :numberfield
200
+ # },
201
+ # :boolean => {
202
+ # :xtype => :numberfield
203
+ # },
204
+ # :date => {
205
+ # :xtype => :datefield
206
+ # },
207
+ # :datetime => {
208
+ # :xtype => :xdatetime
209
+ # # :date_format => "Y-m-d",
210
+ # # :time_format => "H:i",
211
+ # # :time_width => 60
212
+ # },
213
+ # :string => {
214
+ # :xtype => :textfield
215
+ # }
216
+ # }
217
+
218
+ XTYPE_MAP = {
219
+ :integer => :numberfield,
220
+ :boolean => :xcheckbox,
221
+ :date => :datefield,
222
+ :datetime => :xdatetime,
223
+ :string => :textfield
216
224
  }
217
225
 
218
226
  def default_field_config(config)
@@ -224,17 +232,32 @@ module Netzke
224
232
 
225
233
  common = {
226
234
  :field_label => config[:name].to_s.gsub('__', '_').humanize,
227
- :hidden => config[:name] == :id
235
+ :hidden => config[:name] == :id,
236
+ :xtype => XTYPE_MAP[type] || XTYPE_MAP[:string]
228
237
  }
229
238
 
230
- default = DEFAULTS_FOR_FIELD[type] || DEFAULTS_FOR_FIELD[:string] # fallback to plain textfield
239
+ # detect :assoc__method
240
+ if config[:name].to_s.index('__')
241
+ assoc_name, method = config[:name].to_s.split('__').map(&:to_sym)
242
+ if assoc = reflect_on_association(assoc_name)
243
+ assoc_column = assoc.klass.columns_hash[method.to_s]
244
+ assoc_method_type = assoc_column.try(:type)
245
+ if assoc_method_type
246
+ common[:xtype] = ext_editor(assoc_method_type) == :checkbox ? :checkbox : :combobox
247
+ end
248
+ end
249
+ end
250
+
251
+ common.merge(config)
252
+
253
+ # default = DEFAULTS_FOR_FIELD[type] || DEFAULTS_FOR_FIELD[:string] # fallback to plain textfield
231
254
 
232
- res = default.merge(common).merge(config)
255
+ # res = default.merge(common).merge(config)
233
256
  end
234
257
 
235
258
  private
236
259
  def ext_editor(type)
237
- TYPE_EDITOR_MAP[type] || :text_field # fall back to :text_field
260
+ TYPE_EDITOR_MAP[type] || :textfield # fall back to :text_field
238
261
  end
239
262
 
240
263
  end
@@ -115,7 +115,6 @@ module Netzke
115
115
  end
116
116
 
117
117
  def resize_region(params)
118
- logger.debug "!!! params: #{params.inspect}"
119
118
  persistent_config["#{params["region_name"]}_width"] = params["new_width"].to_i if params["new_width"]
120
119
  persistent_config["#{params["region_name"]}_height"] = params["new_height"].to_i if params["new_height"]
121
120
  {}
@@ -1,5 +1,9 @@
1
1
  module Netzke
2
2
  module DbFields
3
+ #
4
+ # Default fields for a widget of class GridPanel or FormPanel
5
+ # It is a synthesis of 1) columns declared in the model, 2) columns provided in the configuration for the widget
6
+ #
3
7
  def default_db_fields
4
8
  config[:data_class_name].nil? && raise(ArgumentError, "No data_class_name specified for widget #{config[:name]}")
5
9
 
@@ -0,0 +1,131 @@
1
+ module Netzke
2
+ class FieldModel < Hash
3
+ include ActiveRecordExtensions
4
+
5
+ def self.new_from_hash(hsh)
6
+ self.new.replace(hsh)
7
+ end
8
+
9
+ # def self.json=(str)
10
+ # @@data = ActiveSupport::JSON.decode(str)
11
+ # process_data
12
+ # end
13
+
14
+ def self.widget_name=(w)
15
+ @@widget_name = w
16
+ end
17
+
18
+ def self.data_storage=(ds)
19
+ @@storage = ds
20
+ process_data
21
+ end
22
+
23
+ # def self.data=(data)
24
+ # @@raw_data = data
25
+ # process_data
26
+ # end
27
+
28
+ def self.column_names
29
+ @@data.inject([]){|res, record| (res + record.keys).uniq}
30
+ end
31
+
32
+ def self.columns
33
+ column_names
34
+ end
35
+
36
+ def self.all(params={})
37
+ @@data
38
+ end
39
+
40
+ def self.first
41
+ @@data[0]
42
+ end
43
+
44
+ def self.find(id)
45
+ @@data[id-1]
46
+ end
47
+
48
+ def self.count(params = {})
49
+ @@data.size
50
+ end
51
+
52
+ def self.columns_hash
53
+ @@columns_hash
54
+ end
55
+
56
+ def self.reflect_on_all_associations
57
+ []
58
+ end
59
+
60
+ # instance methods
61
+ def id
62
+ self[:id] || self["id"]
63
+ end
64
+
65
+ def errors
66
+ []
67
+ end
68
+
69
+ def save
70
+ true
71
+ end
72
+
73
+ private
74
+ def self.process_data
75
+ @@columns_hash = {}
76
+
77
+ @@data = []
78
+
79
+ # convert array of hashes into array of FieldModel instances
80
+ @@storage.each do |hsh|
81
+ @@data << new_from_hash(hsh)
82
+ end
83
+
84
+ @@data.each do |record|
85
+ record.keys.each do |k|
86
+
87
+ if @@columns_hash[k.to_s].nil?
88
+
89
+ # calculate column type
90
+ puts record[k].class.to_s
91
+ column_type = case record[k].class.to_s
92
+ when "TrueClass"
93
+ :boolean
94
+ when "FalseClass"
95
+ :boolean
96
+ when "String"
97
+ :string
98
+ when "Fixnum"
99
+ :integer
100
+ else
101
+ :string
102
+ end
103
+
104
+ column = {:type => column_type}
105
+
106
+ # workaround for the "type" method
107
+ class << column
108
+ def type
109
+ self[:type]
110
+ end
111
+ end
112
+
113
+ @@columns_hash[k.to_s] = column
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ # # Testing
120
+ # @@data = [
121
+ # self.new_from_hash({"id" => 1, "name" => "col1", "column_type" => "text", "read_only" => true}),
122
+ # self.new_from_hash({"id" => 2, "name" => "col2", "column_type" => "string", "read_only" => false})
123
+ # ]
124
+ #
125
+ # process_data
126
+ # end testing
127
+
128
+ end
129
+
130
+
131
+ end