netzke-basepack 0.3.10 → 0.4.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 (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