netzke-basepack 0.3.1 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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] || {}