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.
- data/CHANGELOG +10 -0
- data/Manifest +12 -16
- data/Rakefile +1 -1
- data/TODO +3 -1
- data/autotest/discover.rb +3 -0
- data/javascripts/basepack.js +680 -52
- data/lib/app/models/netzke_hash_record.rb +180 -0
- data/lib/app/models/netzke_layout_item.rb +11 -0
- data/lib/netzke/ar_ext.rb +57 -34
- data/lib/netzke/border_layout_panel.rb +0 -1
- data/lib/netzke/db_fields.rb +4 -0
- data/lib/netzke/field_model.rb +131 -0
- data/lib/netzke/fields_configurator.rb +13 -5
- data/lib/netzke/fields_configurator_old.rb +62 -0
- data/lib/netzke/form_panel.rb +18 -24
- data/lib/netzke/form_panel_extras/interface.rb +20 -13
- data/lib/netzke/form_panel_extras/js_builder.rb +4 -1
- data/lib/netzke/grid_panel.rb +37 -40
- data/lib/netzke/grid_panel_extras/interface.rb +22 -18
- data/lib/netzke/grid_panel_extras/js_builder.rb +42 -13
- data/lib/netzke/property_editor_extras/helper_model.rb +2 -1
- data/lib/netzke/tab_panel.rb +15 -11
- data/netzke-basepack.gemspec +10 -10
- data/test/{accordion_panel_test.rb → unit/accordion_panel_test.rb} +0 -0
- data/test/{ar_ext_test.rb → unit/ar_ext_test.rb} +3 -9
- data/test/{grid_panel_test.rb → unit/grid_panel_test.rb} +0 -5
- data/test/{netzke_basepack_test.rb → unit/netzke_basepack_test.rb} +0 -0
- data/test/unit/netzke_hash_record_test.rb +52 -0
- data/test/unit/netzke_layout_item_test.rb +28 -0
- data/test/{tab_panel_test.rb → unit/tab_panel_test.rb} +0 -0
- metadata +30 -30
- data/generators/netzke_basepack/USAGE +0 -8
- data/generators/netzke_basepack/netzke_basepack_generator.rb +0 -8
- data/generators/netzke_form_panel/netzke_form_panel_generator.rb +0 -7
- data/generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb +0 -21
- data/generators/netzke_grid_panel/netzke_grid_panel_generator.rb +0 -7
- data/generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb +0 -24
- data/lib/app/models/netzke_form_panel_field.rb +0 -51
- data/lib/app/models/netzke_grid_panel_column.rb +0 -56
- data/lib/netzke/form_panel_extras/javascripts/xdatetime.js +0 -634
- data/test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb +0 -23
- 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
|
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
|
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.
|
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
|
150
|
+
assoc_method_type = assoc_column.try(:type)
|
151
151
|
if assoc_method_type
|
152
|
-
res[:editor] = ext_editor(assoc_method_type) == :checkbox ? :checkbox : :
|
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] = :
|
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 => :
|
179
|
+
:integer => :numberfield,
|
180
180
|
:boolean => :checkbox,
|
181
|
-
:date => :
|
182
|
-
:datetime => :
|
183
|
-
:string => :
|
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
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
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
|
-
|
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] || :
|
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
|
{}
|
data/lib/netzke/db_fields.rb
CHANGED
@@ -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
|