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.
- 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
|