netzke-basepack 0.4.2 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.autotest +1 -0
  2. data/.gitignore +6 -0
  3. data/{CHANGELOG → CHANGELOG.rdoc} +26 -0
  4. data/README.rdoc +11 -11
  5. data/Rakefile +37 -11
  6. data/TODO.rdoc +8 -0
  7. data/VERSION +1 -0
  8. data/javascripts/basepack.js +71 -28
  9. data/lib/app/models/netzke_auto_column.rb +56 -0
  10. data/lib/netzke-basepack.rb +5 -3
  11. data/lib/netzke/accordion_panel.rb +69 -67
  12. data/lib/netzke/active_record/basepack.rb +104 -0
  13. data/lib/netzke/active_record/data_accessor.rb +33 -0
  14. data/lib/netzke/basic_app.rb +233 -124
  15. data/lib/netzke/border_layout_panel.rb +97 -98
  16. data/lib/netzke/configuration_panel.rb +24 -0
  17. data/lib/netzke/data_accessor.rb +71 -0
  18. data/lib/netzke/ext.rb +6 -0
  19. data/lib/netzke/field_model.rb +1 -1
  20. data/lib/netzke/fields_configurator.rb +62 -37
  21. data/lib/netzke/form_panel.rb +161 -51
  22. data/lib/netzke/form_panel_api.rb +74 -0
  23. data/lib/netzke/form_panel_js.rb +129 -0
  24. data/lib/netzke/grid_panel.rb +385 -80
  25. data/lib/netzke/grid_panel_api.rb +352 -0
  26. data/lib/netzke/grid_panel_extras/javascripts/rows-dd.js +280 -0
  27. data/lib/netzke/grid_panel_js.rb +721 -0
  28. data/lib/netzke/masquerade_selector.rb +53 -0
  29. data/lib/netzke/panel.rb +9 -0
  30. data/lib/netzke/plugins/configuration_tool.rb +121 -0
  31. data/lib/netzke/property_editor.rb +95 -7
  32. data/lib/netzke/property_editor_extras/helper_model.rb +55 -34
  33. data/lib/netzke/search_panel.rb +62 -0
  34. data/lib/netzke/tab_panel.rb +97 -37
  35. data/lib/netzke/table_editor.rb +49 -44
  36. data/lib/netzke/tree_panel.rb +15 -16
  37. data/lib/netzke/wrapper.rb +29 -5
  38. data/netzke-basepack.gemspec +151 -19
  39. data/stylesheets/basepack.css +5 -0
  40. data/test/app_root/app/models/book.rb +1 -1
  41. data/test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb +1 -1
  42. data/test/unit/accordion_panel_test.rb +1 -2
  43. data/test/unit/active_record_basepack_test.rb +54 -0
  44. data/test/unit/grid_panel_test.rb +8 -12
  45. data/test/unit/helper_model_test.rb +30 -0
  46. metadata +69 -78
  47. data/Manifest +0 -86
  48. data/TODO +0 -3
  49. data/lib/app/models/netzke_hash_record.rb +0 -180
  50. data/lib/app/models/netzke_layout_item.rb +0 -11
  51. data/lib/netzke/ar_ext.rb +0 -269
  52. data/lib/netzke/configuration_tool.rb +0 -80
  53. data/lib/netzke/container.rb +0 -77
  54. data/lib/netzke/db_fields.rb +0 -44
  55. data/lib/netzke/fields_configurator_old.rb +0 -62
  56. data/lib/netzke/form_panel_extras/interface.rb +0 -56
  57. data/lib/netzke/form_panel_extras/js_builder.rb +0 -134
  58. data/lib/netzke/grid_panel_extras/interface.rb +0 -206
  59. data/lib/netzke/grid_panel_extras/js_builder.rb +0 -352
  60. data/test/unit/ar_ext_test.rb +0 -53
  61. data/test/unit/netzke_hash_record_test.rb +0 -52
  62. data/test/unit/netzke_layout_item_test.rb +0 -28
data/Manifest DELETED
@@ -1,86 +0,0 @@
1
- autotest/discover.rb
2
- CHANGELOG
3
- init.rb
4
- install.rb
5
- javascripts/basepack.js
6
- lib/app/models/netzke_hash_record.rb
7
- lib/app/models/netzke_layout_item.rb
8
- lib/netzke/accordion_panel.rb
9
- lib/netzke/ar_ext.rb
10
- lib/netzke/basic_app.rb
11
- lib/netzke/border_layout_panel.rb
12
- lib/netzke/configuration_tool.rb
13
- lib/netzke/container.rb
14
- lib/netzke/db_fields.rb
15
- lib/netzke/field_model.rb
16
- lib/netzke/fields_configurator.rb
17
- lib/netzke/fields_configurator_old.rb
18
- lib/netzke/form_panel.rb
19
- lib/netzke/form_panel_extras/interface.rb
20
- lib/netzke/form_panel_extras/javascripts/xcheckbox.js
21
- lib/netzke/form_panel_extras/js_builder.rb
22
- lib/netzke/grid_panel.rb
23
- lib/netzke/grid_panel_extras/interface.rb
24
- lib/netzke/grid_panel_extras/javascripts/check-column.js
25
- lib/netzke/grid_panel_extras/javascripts/filters.js
26
- lib/netzke/grid_panel_extras/js_builder.rb
27
- lib/netzke/panel.rb
28
- lib/netzke/property_editor.rb
29
- lib/netzke/property_editor_extras/helper_model.rb
30
- lib/netzke/tab_panel.rb
31
- lib/netzke/table_editor.rb
32
- lib/netzke/tree_panel.rb
33
- lib/netzke/wrapper.rb
34
- lib/netzke-basepack.rb
35
- LICENSE
36
- Manifest
37
- Rakefile
38
- README.rdoc
39
- stylesheets/basepack.css
40
- tasks/netzke_basepack_tasks.rake
41
- test/app_root/app/controllers/application.rb
42
- test/app_root/app/models/book.rb
43
- test/app_root/app/models/category.rb
44
- test/app_root/app/models/city.rb
45
- test/app_root/app/models/continent.rb
46
- test/app_root/app/models/country.rb
47
- test/app_root/app/models/genre.rb
48
- test/app_root/config/boot.rb
49
- test/app_root/config/database.yml
50
- test/app_root/config/environment.rb
51
- test/app_root/config/environments/in_memory.rb
52
- test/app_root/config/environments/mysql.rb
53
- test/app_root/config/environments/postgresql.rb
54
- test/app_root/config/environments/sqlite.rb
55
- test/app_root/config/environments/sqlite3.rb
56
- test/app_root/config/routes.rb
57
- test/app_root/db/migrate/20081222033343_create_books.rb
58
- test/app_root/db/migrate/20081222033440_create_genres.rb
59
- test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb
60
- test/app_root/db/migrate/20081223024935_create_categories.rb
61
- test/app_root/db/migrate/20081223025635_create_countries.rb
62
- test/app_root/db/migrate/20081223025653_create_continents.rb
63
- test/app_root/db/migrate/20081223025732_create_cities.rb
64
- test/app_root/db/migrate/20090102223630_create_netzke_layouts.rb
65
- test/app_root/script/console
66
- test/app_root/vendor/plugins/acts_as_list/init.rb
67
- test/app_root/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb
68
- test/app_root/vendor/plugins/acts_as_list/README
69
- test/console_with_fixtures.rb
70
- test/fixtures/books.yml
71
- test/fixtures/categories.yml
72
- test/fixtures/cities.yml
73
- test/fixtures/continents.yml
74
- test/fixtures/countries.yml
75
- test/fixtures/genres.yml
76
- test/schema.rb
77
- test/test_helper.rb
78
- test/unit/accordion_panel_test.rb
79
- test/unit/ar_ext_test.rb
80
- test/unit/grid_panel_test.rb
81
- test/unit/netzke_basepack_test.rb
82
- test/unit/netzke_hash_record_test.rb
83
- test/unit/netzke_layout_item_test.rb
84
- test/unit/tab_panel_test.rb
85
- TODO
86
- uninstall.rb
data/TODO DELETED
@@ -1,3 +0,0 @@
1
- * GridPanel. Reordering of grid columns may lead to unpredictable results when data from an "outdated" table (e.g. open in another browser) gets submitted. A mechanism is needed to submit updated data along with the field names - as hash (as done is FormPanel), *not* as array.
2
-
3
- * Add status bar to BasicApp
@@ -1,180 +0,0 @@
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.persistent_config
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
@@ -1,11 +0,0 @@
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 DELETED
@@ -1,269 +0,0 @@
1
- module Netzke
2
- module ActiveRecordExtensions
3
- def self.included(base)
4
- base.extend ActiveRecordClassMethods
5
- end
6
-
7
- #
8
- # Allow nested association access (assocs separated by "." or "__"), e.g.: proxy_service.asset__gui_folder__name
9
- # Example:
10
- # b = Book.first
11
- # b.genre__name = 'Fantasy' => b.genre = Genre.find_by_name('Fantasy')
12
- # NOT IMPLEMENTED (any real use?): b.genre__catalog__name = 'Best sellers' => b.genre_id = b.genre.find_by_catalog_id(Catalog.find_by_name('Best sellers')).id
13
- #
14
-
15
- def method_missing(method, *args, &block)
16
- # if refering to a column, just pass it to the original method_missing
17
- return super if self.class.column_names.include?(method.to_s)
18
-
19
- split = method.to_s.split(/\.|__/)
20
- if split.size > 1
21
- if split.last =~ /=$/
22
- if split.size == 2
23
- # search for association and assign it to self
24
- assoc = self.class.reflect_on_association(split.first.to_sym)
25
- assoc_method = split.last.chop
26
- if assoc
27
- assoc_instance = assoc.klass.send("find_by_#{assoc_method}", *args)
28
- raise ArgumentError, "Couldn't find association #{split.first} by #{assoc_method} '#{args.first}'" unless assoc_instance
29
- self.send("#{split.first}=", assoc_instance)
30
- else
31
- super
32
- end
33
- else
34
- super
35
- end
36
- else
37
- res = self
38
- split.each do |m|
39
- if res.respond_to?(m)
40
- res = res.send(m) unless res.nil?
41
- else
42
- res.nil? ? nil : super
43
- end
44
- end
45
- res
46
- end
47
- else
48
- super
49
- end
50
- end
51
-
52
- def to_array(columns)
53
- res = []
54
- for c in columns
55
- method = c.is_a?(Symbol) ? c : c[:name]
56
- res << send(method)
57
- end
58
- res
59
- end
60
-
61
- module ActiveRecordClassMethods
62
- # next and previous to id records
63
- def next(id)
64
- find(:first, :conditions => ["#{primary_key} > ?", id])
65
- end
66
- def previous(id)
67
- find(:first, :conditions => ["#{primary_key} < ?", id], :order => "#{primary_key} DESC")
68
- end
69
-
70
- # Returns all unique values for a column, filtered by the query
71
- def choices_for(column, query = nil)
72
- if respond_to?("#{column}_choices", query)
73
- # AR class provides the choices itself
74
- send("#{column}_choices")
75
- else
76
- if (assoc_name, *assoc_method = column.split('__')).size > 1
77
- # column is an association column
78
- assoc_method = assoc_method.join('__') # in case we get something like country__continent__name
79
- association = reflect_on_association(assoc_name.to_sym) || raise(NameError, "Association #{assoc_name} not known for class #{name}")
80
- association.klass.choices_for(assoc_method, query)
81
- else
82
- column = assoc_name
83
- if self.column_names.include?(column)
84
- # it's just a column
85
- records = query.nil? ? find_by_sql("select distinct #{column} from #{table_name}") : find_by_sql("select distinct #{column} from #{table_name} where #{column} like '#{query}%'")
86
- records.map{|r| r.send(column)}
87
- else
88
- # it's a "virtual" column - the least effective search
89
- records = self.find(:all).map{|r| r.send(column)}.uniq
90
- query.nil? ? records : records.select{|r| r.index(/^#{query}/)}
91
- end
92
- end
93
- end
94
- end
95
-
96
- # which columns are to be picked up by grids and forms
97
- def expose_columns(*column_configs)
98
- if column_configs.first == :all
99
- write_inheritable_attribute(:exposed_columns, self.column_names.map(&:to_sym))
100
- else
101
- write_inheritable_attribute(:exposed_columns, column_configs)
102
- end
103
- end
104
-
105
- def exposed_columns
106
- read_inheritable_attribute(:exposed_columns) || write_inheritable_attribute(:exposed_columns, expose_columns(:all) + virtual_columns)
107
- end
108
-
109
- # virtual "columns" that simply correspond to instance methods of an ActiveRecord class
110
- def virtual_column(config)
111
- if config.is_a?(Symbol)
112
- config = {:name => config}
113
- else
114
- config = {:name => config.keys.first}.merge(config.values.first)
115
- end
116
- write_inheritable_attribute(:virtual_columns, (read_inheritable_attribute(:virtual_columns) || []) << config)
117
- end
118
-
119
- def virtual_columns
120
- read_inheritable_attribute(:virtual_columns) || []
121
- end
122
-
123
- def is_virtual_column?(column)
124
- read_inheritable_attribute(:virtual_columns).keys.include?(column)
125
- end
126
-
127
- def default_dbfield_config(config, mode = :grid)
128
- config = config.is_a?(Symbol) ? {:name => config} : config.dup
129
-
130
- # detect ActiveRecord column type (if the column is "real") or fall back to :virtual
131
- type = (columns_hash[config[:name].to_s] && columns_hash[config[:name].to_s].type) || :virtual
132
-
133
- res = {
134
- :name => config[:name].to_s || "unnamed",
135
- :label => config[:label] || config[:name].to_s.gsub('__', '_').humanize,
136
- :read_only => config[:name] == :id, # make "id" column read-only by default
137
- :hidden => config[:name] == :id, # hide "id" column by default
138
- :width => mode == :grid ? DEFAULT_COLUMN_WIDTH : DEFAULT_FIELD_WIDTH,
139
- :editor => ext_editor(type)
140
- }
141
-
142
- # for forms fields also set up the height
143
- res.merge!(:height => DEFAULT_FIELD_HEIGHT) if mode == :form
144
-
145
- # detect :assoc__method
146
- if config[:name].to_s.index('__')
147
- assoc_name, method = config[:name].to_s.split('__').map(&:to_sym)
148
- if assoc = reflect_on_association(assoc_name)
149
- assoc_column = assoc.klass.columns_hash[method.to_s]
150
- assoc_method_type = assoc_column.try(:type)
151
- if assoc_method_type
152
- res[:editor] = ext_editor(assoc_method_type) == :checkbox ? :checkbox : :combobox
153
- end
154
- end
155
- end
156
-
157
- # detect association column (e.g. :category_id)
158
- if assoc = reflect_on_all_associations.detect{|a| a.primary_key_name.to_sym == config[:name]}
159
- res[:editor] = :combobox
160
- assoc_method = %w{name title label}.detect{|m| (assoc.klass.instance_methods + assoc.klass.column_names).include?(m) } || assoc.klass.primary_key
161
- res[:name] = "#{assoc.name}__#{assoc_method}"
162
- end
163
-
164
- res[:width] = 50 if res[:editor] == :checkbox # more narrow column for checkboxes
165
-
166
- # merge with the given confg, which has the priority
167
- config.delete(:name) # because we might have changed the name
168
- res.merge(config)
169
- end
170
-
171
- #
172
- # Used by Netzke::GridPanel
173
- #
174
-
175
- DEFAULT_COLUMN_WIDTH = 100
176
-
177
- # identify Ext editor (xtype) for the data type
178
- TYPE_EDITOR_MAP = {
179
- :integer => :numberfield,
180
- :boolean => :checkbox,
181
- :date => :datefield,
182
- :datetime => :xdatetime,
183
- :string => :textfield
184
- }
185
-
186
- # Returns default column config understood by Netzke::GridPanel
187
- # Argument: column name (as Symbol) or column config
188
- def default_column_config(config)
189
- default_dbfield_config(config, :grid)
190
- end
191
-
192
- #
193
- # Used by Netzke::FormPanel
194
- #
195
-
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
- # }
216
- # }
217
-
218
- XTYPE_MAP = {
219
- :integer => :numberfield,
220
- :boolean => :xcheckbox,
221
- :date => :datefield,
222
- :datetime => :xdatetime,
223
- :string => :textfield
224
- }
225
-
226
- def default_field_config(config)
227
- # default_dbfield_config(config, :form)
228
- config = config.is_a?(Symbol) ? {:name => config} : config.dup
229
-
230
- # detect ActiveRecord column type (if the column is "real") or fall back to :virtual
231
- type = (columns_hash[config[:name].to_s] && columns_hash[config[:name].to_s].type) || :virtual
232
-
233
- common = {
234
- :field_label => config[:name].to_s.gsub('__', '_').humanize,
235
- :hidden => config[:name] == :id,
236
- :xtype => XTYPE_MAP[type] || XTYPE_MAP[:string]
237
- }
238
-
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
254
-
255
- # res = default.merge(common).merge(config)
256
- end
257
-
258
- private
259
- def ext_editor(type)
260
- TYPE_EDITOR_MAP[type] || :textfield # fall back to :text_field
261
- end
262
-
263
- end
264
- end
265
- end
266
-
267
- ActiveRecord::Base.class_eval do
268
- include Netzke::ActiveRecordExtensions
269
- end