netzke-basepack 0.3.1 → 0.3.3

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 (35) hide show
  1. data/CHANGELOG +22 -0
  2. data/Manifest +6 -4
  3. data/README.rdoc +2 -2
  4. data/Rakefile +1 -1
  5. data/generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb +5 -6
  6. data/generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb +2 -1
  7. data/javascripts/basepack.js +2 -0
  8. data/lib/app/models/netzke_form_panel_field.rb +35 -3
  9. data/lib/app/models/netzke_grid_panel_column.rb +39 -2
  10. data/lib/netzke-basepack.rb +0 -1
  11. data/lib/netzke/accordion_panel.rb +51 -15
  12. data/lib/netzke/ar_ext.rb +14 -6
  13. data/lib/netzke/basic_app.rb +5 -5
  14. data/lib/netzke/border_layout_panel.rb +19 -4
  15. data/lib/netzke/container.rb +2 -6
  16. data/lib/netzke/db_fields.rb +40 -0
  17. data/lib/netzke/fields_configurator.rb +10 -18
  18. data/lib/netzke/form_panel.rb +42 -128
  19. data/lib/netzke/form_panel_extras/interface.rb +49 -0
  20. data/lib/netzke/form_panel_extras/js_builder.rb +131 -0
  21. data/lib/netzke/grid_panel.rb +20 -12
  22. data/lib/netzke/grid_panel_extras/interface.rb +181 -0
  23. data/lib/netzke/grid_panel_extras/js_builder.rb +322 -0
  24. data/lib/netzke/table_editor.rb +110 -0
  25. data/lib/netzke/wrapper.rb +1 -3
  26. data/netzke-basepack.gemspec +8 -8
  27. data/test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb +3 -1
  28. data/test/border_layout_panel_test.rb +8 -12
  29. data/test/grid_panel_test.rb +3 -3
  30. data/test/test_helper.rb +8 -0
  31. metadata +15 -11
  32. data/lib/netzke/column.rb +0 -50
  33. data/lib/netzke/grid_panel_interface.rb +0 -167
  34. data/lib/netzke/grid_panel_js_builder.rb +0 -298
  35. data/test/column_test.rb +0 -27
data/CHANGELOG CHANGED
@@ -1,3 +1,25 @@
1
+ v0.3.3
2
+ Bug fix: application not loading the widget specified in the URL (Ext.History-related).
3
+ Some code refactoring and readability improvements.
4
+ Ext.componentCache renamed into Ext.netzke.cache.
5
+ New widget: TableEditor (a compound widget containing a grid and a form for editing table data).
6
+ BorderLayoutPanel: a function getRegionWidget(region) added to access a widget in the specified region.
7
+ Bug fix: BasicApp: FeedbackGhost now gets instantiated before BasicApp.
8
+ Clearer handling of requests to non-existing aggregatees.
9
+ Bug fix: now Ext 2.2.1 compatible.
10
+ Column operations are now handled properly when :persistent_layout is set to false.
11
+ Grid/Form fields configuration is extended with "ext_config" field which stores (in JSON-format) all the extra configuration, which gives extra flexibility to individual column/field configuration.
12
+ :persistent_layout set to false now makes a widget ignore what's in the DB.
13
+ Bug fix: AccordionPanel doesn't crash when no active item is specified.
14
+ Bug fix: redundant flash messages for GridPanel.
15
+ FeedbackGhost won't be showing anything if given an empty array.
16
+ Cleaner handling of validations in GridPanel.
17
+ FormPanel ready for the demo.
18
+
19
+ v0.3.2
20
+ Minor code restructuring.
21
+ Working on FormPanel cont'd.
22
+
1
23
  v0.3.1
2
24
  Added the "conditions" configuration option to GridPanel to limit the search
3
25
  Basic column editor for grids has been replaced with FieldsConfigurator, which can do a bit more
data/Manifest CHANGED
@@ -17,17 +17,20 @@ lib/netzke/accordion_panel.rb
17
17
  lib/netzke/ar_ext.rb
18
18
  lib/netzke/basic_app.rb
19
19
  lib/netzke/border_layout_panel.rb
20
- lib/netzke/column.rb
21
20
  lib/netzke/container.rb
21
+ lib/netzke/db_fields.rb
22
22
  lib/netzke/fields_configurator.rb
23
23
  lib/netzke/form_panel.rb
24
+ lib/netzke/form_panel_extras/interface.rb
25
+ lib/netzke/form_panel_extras/js_builder.rb
24
26
  lib/netzke/grid_panel.rb
25
- lib/netzke/grid_panel_interface.rb
26
- lib/netzke/grid_panel_js_builder.rb
27
+ lib/netzke/grid_panel_extras/interface.rb
28
+ lib/netzke/grid_panel_extras/js_builder.rb
27
29
  lib/netzke/panel.rb
28
30
  lib/netzke/preference_grid.rb
29
31
  lib/netzke/properties_tool.rb
30
32
  lib/netzke/property_grid.rb
33
+ lib/netzke/table_editor.rb
31
34
  lib/netzke/wrapper.rb
32
35
  lib/netzke-basepack.rb
33
36
  LICENSE
@@ -66,7 +69,6 @@ test/app_root/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb
66
69
  test/app_root/vendor/plugins/acts_as_list/README
67
70
  test/ar_ext_test.rb
68
71
  test/border_layout_panel_test.rb
69
- test/column_test.rb
70
72
  test/console_with_fixtures.rb
71
73
  test/fixtures/books.yml
72
74
  test/fixtures/categories.yml
data/README.rdoc CHANGED
@@ -1,5 +1,5 @@
1
1
  = netzke-basepack
2
- A pack of basic Rails/Ext JS widgets, as a part of Netzke framework. Live demo/tutorials on http://blog.writelesscode.com
2
+ A pack of basic Rails/ExtJS widgets as a part of the Netzke framework. Live demo/tutorials on http://blog.writelesscode.com. Introduction to the Netzke framework: http://github.com/skozlov/netzke/tree/master
3
3
 
4
4
  Note that if you would like to modify this code or experiment with it, you may be better off cloning this project into your app's vendor/plugin directory - it will then behave as a Rails plugin.
5
5
 
@@ -84,4 +84,4 @@ TODO: this part will be covered later
84
84
  = Credentials
85
85
  Testing done with the help of http://github.com/pluginaweek/plugin_test_helper
86
86
 
87
- Copyright (c) 2009 Sergei Kozlov, released under the MIT license
87
+ Copyright (c) 2008-2009 Sergei Kozlov, released under the MIT license
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ Echoe.new("netzke-basepack") do |p|
5
5
  p.email = "sergei@writelesscode.com"
6
6
  p.summary = "Base Netzke widgets - grid, form, tree, and more"
7
7
  p.url = "http://writelesscode.com"
8
- p.runtime_dependencies = ["searchlogic >=1.6.2", "netzke-core >= 0.2.4"]
8
+ p.runtime_dependencies = ["searchlogic >=1.6.2", "netzke-core >= 0.2.6"]
9
9
  p.development_dependencies = []
10
10
  p.test_pattern = 'test/**/*_test.rb'
11
11
 
@@ -2,14 +2,13 @@ class CreateNetzkeFormPanelFields < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table :netzke_form_panel_fields do |t|
4
4
  t.string :name
5
- t.string :label
6
- t.boolean :read_only
7
- t.integer :position
5
+ t.string :field_label
8
6
  t.boolean :hidden
9
- t.integer :width
10
- t.integer :height
11
- t.string :editor, :limit => 32
7
+ t.boolean :disabled
8
+ t.string :xtype
9
+ t.string :ext_config, :limit => 1024
12
10
 
11
+ t.integer :position
13
12
  t.integer :layout_id
14
13
 
15
14
  t.timestamps
@@ -4,12 +4,13 @@ class CreateNetzkeGridPanelColumns < ActiveRecord::Migration
4
4
  t.string :name
5
5
  t.string :label
6
6
  t.boolean :read_only
7
- t.integer :position
8
7
  t.boolean :hidden
9
8
  t.integer :width
10
9
  t.string :editor, :limit => 32
11
10
  t.string :renderer, :limit => 32
11
+ t.string :ext_config, :limit => 1024
12
12
 
13
+ t.integer :position
13
14
  t.integer :layout_id
14
15
 
15
16
  t.timestamps
@@ -1,3 +1,5 @@
1
+ Ext.apply(Ext.History, new Ext.util.Observable());
2
+
1
3
  // Editors for grid cells and form fields
2
4
  Ext.netzke.editors = {
3
5
  combo_box: function(c, config){
@@ -3,16 +3,48 @@ class NetzkeFormPanelField < ActiveRecord::Base
3
3
 
4
4
  acts_as_list :scope => :layout
5
5
 
6
+ validate :valid_ext_config
7
+
8
+ expose_columns :id,
9
+ :name,
10
+ :field_label,
11
+ :hidden,
12
+ {:name => :disabled, :renderer => "checkbox"},
13
+ :ext_config
14
+
15
+
6
16
  def self.create_layout_for_widget(widget)
7
- layout = NetzkeLayout.create(:widget_name => widget.id_name, :items_class => self.name, :user_id => NetzkeLayout.user_id)
17
+ layout = NetzkeLayout.create_with_user(:widget_name => widget.id_name, :items_class => self.name)
8
18
 
9
- columns = Netzke::Column.default_fields_for_widget(widget)
19
+ columns = widget.default_db_fields
10
20
 
11
21
  for c in columns
12
22
  config_for_create = c.merge(:layout_id => layout.id).stringify_values!
13
- create(config_for_create)
23
+ new_field = self.new
24
+ ext_config = {}
25
+ for k in config_for_create.keys
26
+ if new_field.respond_to?("#{k}=")
27
+ new_field.send("#{k}=", config_for_create[k])
28
+ else
29
+ ext_config[k] = config_for_create[k]
30
+ end
31
+ end
32
+ new_field.ext_config = ext_config.to_js
33
+ new_field.save!
14
34
  end
15
35
 
16
36
  layout
17
37
  end
38
+
39
+ private
40
+
41
+ def valid_ext_config
42
+ begin
43
+ JSON.parse(ext_config)
44
+ rescue
45
+ errors.add(:ext_config, "is not valid JSON")
46
+ end
47
+ end
48
+
49
+
18
50
  end
@@ -3,15 +3,52 @@ class NetzkeGridPanelColumn < ActiveRecord::Base
3
3
 
4
4
  acts_as_list :scope => :layout
5
5
 
6
+ validate :valid_ext_config
7
+
8
+ expose_columns :id,
9
+ :name,
10
+ :label,
11
+ {:name => :read_only, :label => "R/O"},
12
+ :hidden,
13
+ {:name => :width, :width => 50},
14
+ {:name => :editor, :editor => :combo_box},
15
+ {:name => :renderer, :editor => :combo_box},
16
+ :ext_config
17
+
6
18
  def self.create_layout_for_widget(widget)
7
19
  layout = NetzkeLayout.create_with_user(:widget_name => widget.id_name, :items_class => self.name)
8
- columns = Netzke::Column.default_columns_for_widget(widget)
20
+ columns = widget.default_db_fields
9
21
 
10
22
  for c in columns
11
23
  config_for_create = c.merge(:layout_id => layout.id).stringify_values!
12
- create(config_for_create)
24
+ new_field = self.new
25
+ ext_config = {}
26
+ for k in config_for_create.keys
27
+ if new_field.respond_to?("#{k}=")
28
+ new_field.send("#{k}=", config_for_create[k])
29
+ else
30
+ ext_config[k] = config_for_create[k]
31
+ end
32
+ end
33
+
34
+ new_field.ext_config = ext_config.to_js
35
+ new_field.save!
36
+
37
+ # config_for_create = c.merge(:layout_id => layout.id).stringify_values!
38
+ # create(config_for_create)
13
39
  end
14
40
 
15
41
  layout
16
42
  end
43
+
44
+ private
45
+
46
+ def valid_ext_config
47
+ begin
48
+ JSON.parse(ext_config)
49
+ rescue
50
+ errors.add(:ext_config, "is not valid JSON")
51
+ end
52
+ end
53
+
17
54
  end
@@ -20,7 +20,6 @@ end
20
20
  Netzke::Base.config[:javascripts] << "#{File.dirname(__FILE__)}/../javascripts/basepack.js"
21
21
  Netzke::Base.config[:javascripts] << "#{File.dirname(__FILE__)}/../javascripts/check_column.js"
22
22
 
23
- # TODO: implement configurable loading of JS, to spare the traffic at the initial loading
24
23
  extjs_dir = "#{RAILS_ROOT}/public/extjs"
25
24
 
26
25
  # Filters in GridPanel
@@ -1,15 +1,26 @@
1
1
  module Netzke
2
+ #
3
+ # AccordionPanel
4
+ #
5
+ # Features:
6
+ # * Dynamically loads widgets for the panels that get expanded for the first time
7
+ # * Gets loaded along with the widget that is to be put into the active (expanded) panel (saves us a server request)
8
+ #
9
+ # TODO:
10
+ # * Stores the last active panel in the persistent_configuration
11
+ #
2
12
  class AccordionPanel < Base
3
13
  #
4
14
  # JS-class generation
5
15
  #
6
- class << self
16
+ module ClassMethods
7
17
 
8
18
  def js_default_config
9
19
  super.merge({
10
20
  :layout => 'accordion',
21
+ :defaults => {:layout => 'fit'}, # all items will be of type Panel with layout 'fit'
11
22
  :listeners => {
12
- # every item gets an expand event activeted, which dynamically loads a widget into this item
23
+ # every item gets an expand event set, which dynamically loads a widget into this item
13
24
  :add => {
14
25
  :fn => <<-JS.l
15
26
  function(self, comp){
@@ -26,19 +37,50 @@ module Netzke
26
37
  # loads widget into the panel if it wasn't loaded yet
27
38
  :load_item_widget => <<-JS.l,
28
39
  function(panel) {
29
- if (!panel.getWidget()) panel.loadWidget(this.id + "__" + panel.id + "__get_widget");
40
+ if (!panel.getWidget()) panel.loadWidget(this.id + "__" + panel.containerFor + "__get_widget");
41
+ }
42
+ JS
43
+
44
+ :on_widget_load => <<-JS.l
45
+ function(){
46
+ // immediately instantiate the active panel
47
+ var activePanel = this.findById(this.id + "_active");
48
+ var activeItemConfig = this.initialConfig[this.initialConfig.expandedItem+"Config"];
49
+ if (activeItemConfig) activePanel.add(new Ext.netzke.cache[activeItemConfig.widgetClassName](activeItemConfig));
30
50
  }
31
51
  JS
32
52
  }
33
53
  end
54
+ end
55
+ extend ClassMethods
56
+
57
+ # some configuration normalization
58
+ def initialize(*args)
59
+ super
60
+
61
+ seen_active = false
62
+
63
+ config[:items].each_with_index do |item, i|
64
+ # if some items are provided without names, give them generated names
65
+ item[:name] ||= "item#{i}"
34
66
 
67
+ # remove duplucated :active configuration
68
+ if item[:active]
69
+ item[:active] = nil if seen_active
70
+ seen_active = true
71
+ end
72
+ end
35
73
  end
36
74
 
37
75
  def js_config
38
- super.merge(:items => items)
76
+ expanded_widget_config = config[:items].select{|i| i[:active]}.first
77
+ super.merge({
78
+ :items => items,
79
+ :expanded_item => expanded_widget_config && expanded_widget_config[:name]
80
+ })
39
81
  end
40
82
 
41
- # the items are late aggregatees (besides the ones that are marked "active")
83
+ # the items are late aggregatees, besides the ones that are marked "active"
42
84
  def initial_aggregatees
43
85
  res = {}
44
86
  config[:items].each_with_index do |item, i|
@@ -48,22 +90,16 @@ module Netzke
48
90
  res
49
91
  end
50
92
 
93
+ # configuration for items (fit-panels)
51
94
  def items
52
95
  res = []
53
96
  config[:items].each_with_index do |item, i|
54
97
  item_config = {
55
- :id => item[:name] || "item_#{i}",
56
- :title => item[:title] || (item[:name] && item[:name].humanize) || "Item #{i}",
57
- :layout => 'fit',
98
+ :id => item[:active] && id_name + '_active',
99
+ :title => item[:title] || (item[:name] && item[:name].humanize),
100
+ :container_for => item[:name], # to know which fit panel will load which widget
58
101
  :collapsed => !(item[:active] || false)
59
102
  }
60
-
61
- # directly embed the widget in the active panel
62
- if item[:active]
63
- item_instance = Netzke::Base.instance_by_config(item.merge(:name => "#{id_name}__#{item[:name]}"))
64
- item_config[:items] = ["new Ext.componentCache['#{item[:widget_class_name]}'](#{item_instance.js_config.to_js})".l]
65
- end
66
-
67
103
  res << item_config
68
104
  end
69
105
  res
data/lib/netzke/ar_ext.rb CHANGED
@@ -193,13 +193,21 @@ module Netzke
193
193
  # detect ActiveRecord column type (if the column is "real") or fall back to :virtual
194
194
  type = (columns_hash[config[:name].to_s] && columns_hash[config[:name].to_s].type) || :virtual
195
195
 
196
- res = {
197
- :name => config[:name].to_s || "unnamed",
198
- :field_label => config[:field_label] || config[:name].to_s.gsub('__', '_').humanize,
199
- :disabled => config[:name] == :id, # make "id" column disabled by default
200
- # :hidden => config[:name] == :id, # hide "id" column by default
201
- :xtype => XTYPE_MAP[type]
196
+ defaults = {
197
+ :field_label => config[:name].to_s.gsub('__', '_').humanize,
198
+ :xtype => XTYPE_MAP[type],
199
+ :hidden => config[:name] == :id
202
200
  }
201
+
202
+ res = defaults.merge(config)
203
+
204
+ # res = {
205
+ # :name => config[:name].to_s || "unnamed",
206
+ # :field_label => config[:field_label] || config[:name].to_s.gsub('__', '_').humanize,
207
+ # # :disabled => config[:name] == :id, # make "id" column disabled by default
208
+ # # :hidden => config[:name] == :id, # hide "id" column by default
209
+ # :xtype => XTYPE_MAP[type]
210
+ # }
203
211
 
204
212
  end
205
213
 
@@ -96,8 +96,6 @@ module Netzke
96
96
  // Initialize menus (upcoming support for dynamically loaded menus)
97
97
  this.menus = {};
98
98
 
99
- // Initialize history
100
- Ext.History.init();
101
99
  Ext.History.on('change', this.processHistory, this);
102
100
 
103
101
  // If we are given a token, load the corresponding widget, otherwise load the last loaded widget
@@ -168,9 +166,11 @@ module Netzke
168
166
 
169
167
  # Besides instantiating ourselves, also instantiate the FeedbackGhost
170
168
  def js_widget_instance
171
- super << %Q{
172
- new Ext.componentCache['FeedbackGhost']({id:'feedback_ghost'})
173
- }
169
+ %Q{
170
+ new Ext.netzke.cache['FeedbackGhost']({id:'feedback_ghost'})
171
+ // Initialize history (can't say why it's not working well inside the appLoaded handler)
172
+ Ext.History.init();
173
+ } << super
174
174
  end
175
175
 
176
176
  # Interface implementation
@@ -7,7 +7,7 @@ module Netzke
7
7
  #
8
8
  # JS-class generation
9
9
  #
10
- class << self
10
+ module ClassMethods
11
11
  def js_listeners
12
12
  {
13
13
  :afterlayout => {:fn => "this.setResizeEvents".l, :scope => this}
@@ -23,8 +23,17 @@ module Netzke
23
23
  var regionConfig = config.regions[r] || {};
24
24
  regionConfig.layout = 'fit';
25
25
  regionConfig.region = r;
26
- regionConfig.items = [new Ext.componentCache[config[configName].widgetClassName](config[configName])]
26
+ regionConfig.items = [new Ext.netzke.cache[config[configName].widgetClassName](config[configName])]
27
27
  items.push(regionConfig);
28
+
29
+ // A function to access a region widget (even if the widget gets reloaded, the function will work).
30
+ // E.g.: getEastWidget()
31
+ // I love JavaScript
32
+ this['get'+r.capitalize()+'Widget'] = function(){
33
+ return this.find('region', r)[0].getWidget()
34
+ }.createDelegate(this)
35
+
36
+
28
37
  };
29
38
  }, this)
30
39
  JS
@@ -38,7 +47,13 @@ module Netzke
38
47
  end
39
48
 
40
49
  def js_extend_properties
41
- {:set_resize_events => <<-JS.l,
50
+ {
51
+ :get_region_widget => <<-JS.l,
52
+ function(region){
53
+ return this.find('region', region)[0].getWidget()
54
+ }
55
+ JS
56
+ :set_resize_events => <<-JS.l,
42
57
  function(){
43
58
  this.items.each(function(item, index, length){
44
59
  if (!item.oldSize) item.oldSize = item.getSize();
@@ -68,8 +83,8 @@ module Netzke
68
83
  JS
69
84
  }
70
85
  end
71
-
72
86
  end
87
+ extend ClassMethods
73
88
 
74
89
  def initial_aggregatees
75
90
  config[:regions] || {}