netzke-basepack 0.2.0.1 → 0.2.2

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 CHANGED
@@ -1,3 +1,9 @@
1
+ v0.2.2
2
+ Meta: updated netzke-core version (dependency)
3
+
4
+ v0.2.1
5
+ Regression: BorderLayoutPanel now restores the region sizes from the database
6
+
1
7
  v0.2.0.1
2
8
  Meta: updated netzke-core version (dependency)
3
9
 
data/Manifest CHANGED
@@ -1,19 +1,23 @@
1
1
  CHANGELOG
2
2
  css/basepack.css
3
3
  generators/netzke_basepack/netzke_basepack_generator.rb
4
- generators/netzke_basepack/netzke_grid_panel_generator.rb
5
- generators/netzke_basepack/templates/create_netzke_grid_panel_columns.rb
6
4
  generators/netzke_basepack/USAGE
5
+ generators/netzke_form_panel/netzke_form_panel_generator.rb
6
+ generators/netzke_form_panel/templates/create_netzke_form_panel_fields.rb
7
+ generators/netzke_grid_panel/netzke_grid_panel_generator.rb
8
+ generators/netzke_grid_panel/templates/create_netzke_grid_panel_columns.rb
7
9
  init.rb
8
10
  install.rb
9
11
  javascripts/basepack.js
10
12
  javascripts/filters.js
13
+ lib/app/models/netzke_form_panel_field.rb
11
14
  lib/app/models/netzke_grid_panel_column.rb
12
15
  lib/netzke/accordion_panel.rb
13
16
  lib/netzke/ar_ext.rb
14
17
  lib/netzke/border_layout_panel.rb
15
18
  lib/netzke/column.rb
16
19
  lib/netzke/container.rb
20
+ lib/netzke/form_panel.rb
17
21
  lib/netzke/grid_panel.rb
18
22
  lib/netzke/grid_panel_interface.rb
19
23
  lib/netzke/grid_panel_js_builder.rb
@@ -26,7 +30,7 @@ lib/netzke-basepack.rb
26
30
  LICENSE
27
31
  Manifest
28
32
  Rakefile
29
- README.mdown
33
+ README.rdoc
30
34
  tasks/netzke_basepack_tasks.rake
31
35
  test/app_root/app/controllers/application.rb
32
36
  test/app_root/app/models/book.rb
@@ -51,7 +55,12 @@ test/app_root/db/migrate/20081223024935_create_categories.rb
51
55
  test/app_root/db/migrate/20081223025635_create_countries.rb
52
56
  test/app_root/db/migrate/20081223025653_create_continents.rb
53
57
  test/app_root/db/migrate/20081223025732_create_cities.rb
58
+ test/app_root/db/migrate/20090102223630_create_netzke_layouts.rb
59
+ test/app_root/db/migrate/20090102223811_create_netzke_grid_panel_columns.rb
54
60
  test/app_root/script/console
61
+ test/app_root/vendor/plugins/acts_as_list/init.rb
62
+ test/app_root/vendor/plugins/acts_as_list/lib/active_record/acts/list.rb
63
+ test/app_root/vendor/plugins/acts_as_list/README
55
64
  test/ar_ext_test.rb
56
65
  test/border_layout_panel_test.rb
57
66
  test/column_test.rb
data/README.rdoc ADDED
@@ -0,0 +1,87 @@
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
3
+
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
+
6
+ = Prerequisites
7
+ 1. Rails >= 2.2
8
+ 2. Ext JS >= 2.0: its root *must* be accessible as RAILS_ROOT/public/extjs. You may symlink your Ext JS library here like this (from your app folder):
9
+ cd public && ln -s ~/Developer/extjs/ext-2.2 extjs
10
+
11
+ 3. acts_as_list plugin must be installed:
12
+ ./script/plugin install git://github.com/rails/acts_as_list.git
13
+
14
+ = Installation
15
+ Install the gem:
16
+ gem install netzke-basepack
17
+
18
+ Include it into environment.rb:
19
+ config.gem "netzke-basepack"
20
+
21
+ Include mapping for Netzke controller providing *.js and *.css (in routes.rb):
22
+ map.netzke
23
+
24
+ = Usage
25
+ First, run the generators to have the necessary migrations:
26
+ ./script/generate netzke_core
27
+ ./script/generate netzke_grid_panel
28
+
29
+ Do the migrations:
30
+ rake db:migrate
31
+
32
+ The following example will provide you with a grid-based scaffold for ActiveRecord-model called Book. You may generate it like this:
33
+ ./script/generate model Book title:string amount:integer
34
+ (don't forget to run the migrations after it)
35
+
36
+ In the controller declare the widget:
37
+
38
+ class WelcomeController < ApplicationController
39
+ netzke :books, :widget_class_name => 'GridPanel', :data_class_name => 'Book'
40
+ end
41
+
42
+ After a widget is declared in the controller, it can be accessed in 3 different ways: 1) loaded by means of an automatically created controller action which will produce a basic HTML-page with the widget (handy for testing), 2) embedded directly into a view (by means of helpers), 3) dynamically loaded by other widgets (usually by the widget of class 'Application', if you want a desktop-like, AJAX-driven web-app).
43
+
44
+ == Using automatically created controller action
45
+ Without writing any more code, you can access the widget by http://localhost:3000/welcome/books_test. That is to say, you simply append _test to your widget's name (as declared in the controller) to get the action name.
46
+
47
+ == Embedding a widget into a view
48
+ netzke-core plugin provides the following 2 helpers to put inside your head-tag (use it in your layout):
49
+
50
+ 1. netzke_js_include - to include extjs and netzke javascript files
51
+ 2. netzke_css_include - to include the css. This one can take a parameter to specify a color schema you wish for Ext JS, e.g.: netzke_css_include(:gray)
52
+
53
+ Declaring a widget in the controller provides you with a couple of helpers that can be used in the view:
54
+
55
+ 1. books_class_definition will contain the javascript code defining the code for the JS class.
56
+ 2. books_widget_instance will declare a local javascript variable called book.
57
+
58
+ Use these helpers inside of the script-tag like the following (in the view):
59
+
60
+ <script type="text/javascript" charset="utf-8">
61
+ <%= books_class_definition %>
62
+ Ext.onReady(function(){
63
+ <%= books_widget_instance %>
64
+ books.render("books");
65
+ })
66
+ </script>
67
+ <div id="books">the widget will be rendered in this div</div>
68
+
69
+ If your layout already calls yield :javascripts wrapped in the <script>-tag, you can have all javascript-code in one place on the page:
70
+
71
+ <% content_for :javascripts do %>
72
+ <%= books_class_definition %>
73
+ Ext.onReady(function(){
74
+ <%= books_widget_instance %>
75
+ books.render("books");
76
+ })
77
+ <% end %>
78
+ <p>... your page content here ...</p>
79
+ <div id="books">the widget will be rendered in this div</div>
80
+
81
+ == Dynamic loading of widgets
82
+ TODO: this part will be covered later
83
+
84
+ = Credentials
85
+ Testing done with the help of http://github.com/pluginaweek/plugin_test_helper
86
+
87
+ Copyright (c) 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.1"]
8
+ p.runtime_dependencies = ["searchlogic >=1.6.2", "netzke-core >= 0.2.2"]
9
9
  p.development_dependencies = []
10
10
  p.test_pattern = 'test/**/*_test.rb'
11
11
 
@@ -0,0 +1,7 @@
1
+ class NetzkeFormPanelGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'create_netzke_form_panel_fields.rb', "db/migrate", {:migration_file_name => "create_netzke_form_panel_fields"}
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ class CreateNetzkeFormPanelFields < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :netzke_form_panel_fields do |t|
4
+ t.string :name
5
+ t.string :label
6
+ t.boolean :read_only
7
+ t.integer :position
8
+ t.boolean :hidden
9
+ t.integer :width
10
+ t.integer :height
11
+ t.string :editor, :limit => 32
12
+
13
+ t.integer :layout_id
14
+
15
+ t.timestamps
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ drop_table :netzke_form_panel_fields
21
+ end
22
+ end
@@ -49,4 +49,34 @@ Ext.netzke.filterMap = {
49
49
  checkbox:'Boolean',
50
50
  combo_box:'String',
51
51
  date:'Date'
52
- }
52
+ }
53
+
54
+ Ext.data.RecordArrayReader = Ext.extend(Ext.data.JsonReader, {
55
+ /**
56
+ * Create a data block containing Ext.data.Records from an Array.
57
+ * @param {Object} o An Array of row objects which represents the dataset.
58
+ * @return {Object} data A data block which is used by an Ext.data.Store object as
59
+ * a cache of Ext.data.Records.
60
+ */
61
+ readRecord : function(o){
62
+ var sid = this.meta ? this.meta.id : null;
63
+ var recordType = this.recordType, fields = recordType.prototype.fields;
64
+ var records = [];
65
+ var root = o;
66
+ // for(var i = 0; i < root.length; i++){
67
+ var n = root;
68
+ var values = {};
69
+ var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
70
+ for(var j = 0, jlen = fields.length; j < jlen; j++){
71
+ var f = fields.items[j];
72
+ var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
73
+ var v = n[k] !== undefined ? n[k] : f.defaultValue;
74
+ v = f.convert(v, n);
75
+ values[f.name] = v;
76
+ }
77
+ var record = new recordType(values, id);
78
+ record.json = n;
79
+ // }
80
+ return record;
81
+ }
82
+ });
@@ -0,0 +1,18 @@
1
+ class NetzkeFormPanelField < ActiveRecord::Base
2
+ belongs_to :layout, :class_name => "NetzkeLayout"
3
+
4
+ acts_as_list :scope => :layout
5
+
6
+ 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)
8
+
9
+ columns = Netzke::Column.default_fields_for_widget(widget)
10
+
11
+ for c in columns
12
+ config_for_create = c.merge(:layout_id => layout.id).stringify_values!
13
+ create(config_for_create)
14
+ end
15
+
16
+ layout
17
+ end
18
+ end
@@ -3,14 +3,8 @@ class NetzkeGridPanelColumn < ActiveRecord::Base
3
3
 
4
4
  acts_as_list :scope => :layout
5
5
 
6
- # old?
7
- # def self.create_with_defaults(column_config, klass)
8
- # create(klass.default_column_config(column_config).stringify_values!)
9
- # end
10
-
11
6
  def self.create_layout_for_widget(widget)
12
- layout = NetzkeLayout.create(:widget_name => widget.id_name, :items_class => self.name, :user_id => NetzkeLayout.user_id)
13
-
7
+ layout = NetzkeLayout.create_with_user(:widget_name => widget.id_name, :items_class => self.name)
14
8
  columns = Netzke::Column.default_columns_for_widget(widget)
15
9
 
16
10
  for c in columns
data/lib/netzke/ar_ext.rb CHANGED
@@ -49,7 +49,24 @@ module Netzke
49
49
  end
50
50
  end
51
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
+
52
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
+
53
70
  # Returns all unique values for a column, filtered by the query
54
71
  def choices_for(column, query = nil)
55
72
  if respond_to?("#{column}_choices", query)
@@ -107,18 +124,8 @@ module Netzke
107
124
  read_inheritable_attribute(:virtual_columns).keys.include?(column)
108
125
  end
109
126
 
110
- #
111
- # Used by Netzke::GridPanel
112
- #
113
-
114
- DEFAULT_COLUMN_WIDTH = 100
115
-
116
- # Returns default column config understood by Netzke::GridPanel
117
- # Argument: column name (as Symbol) or column config
118
- def default_column_config(config)
119
- config = config.dup
120
- # config = config.dup # to not touch the original config
121
- config = {:name => config} if config.is_a?(Symbol) # if got a column name
127
+ def default_dbfield_config(config, mode = :grid)
128
+ config = config.is_a?(Symbol) ? {:name => config} : config.dup
122
129
 
123
130
  # detect ActiveRecord column type (if the column is "real") or fall back to :virtual
124
131
  type = (columns_hash[config[:name].to_s] && columns_hash[config[:name].to_s].type) || :virtual
@@ -128,9 +135,12 @@ module Netzke
128
135
  :label => config[:label] || config[:name].to_s.gsub('__', '_').humanize,
129
136
  :read_only => config[:name] == :id, # make "id" column read-only by default
130
137
  :hidden => config[:name] == :id, # hide "id" column by default
131
- :width => DEFAULT_COLUMN_WIDTH,
138
+ :width => mode == :grid ? DEFAULT_COLUMN_WIDTH : DEFAULT_FIELD_WIDTH,
132
139
  :editor => ext_editor(type)
133
140
  }
141
+
142
+ # for forms fields also set up the height
143
+ res.merge!(:height => DEFAULT_FIELD_HEIGHT) if mode == :form
134
144
 
135
145
  # detect :assoc__method
136
146
  if config[:name].to_s.index('__')
@@ -157,13 +167,38 @@ module Netzke
157
167
  end
158
168
 
159
169
  #
160
- # Used by Netzke::Form
170
+ # Used by Netzke::GridPanel
171
+ #
172
+
173
+ DEFAULT_COLUMN_WIDTH = 100
174
+
175
+ # Returns default column config understood by Netzke::GridPanel
176
+ # Argument: column name (as Symbol) or column config
177
+ def default_column_config(config)
178
+ default_dbfield_config(config, :grid)
179
+ end
180
+
181
+ #
182
+ # Used by Netzke::FormPanel
161
183
  #
162
184
 
163
185
  DEFAULT_FIELD_WIDTH = 100
164
- DEFAULT_FIELD_HEIGHT = 50
186
+ DEFAULT_FIELD_HEIGHT = nil
165
187
  def default_field_config(config)
166
- # TODO
188
+ # default_dbfield_config(config, :form)
189
+ config = config.is_a?(Symbol) ? {:name => config} : config.dup
190
+
191
+ # detect ActiveRecord column type (if the column is "real") or fall back to :virtual
192
+ type = (columns_hash[config[:name].to_s] && columns_hash[config[:name].to_s].type) || :virtual
193
+
194
+ res = {
195
+ :name => config[:name].to_s || "unnamed",
196
+ :field_label => config[:field_label] || config[:name].to_s.gsub('__', '_').humanize,
197
+ :disabled => config[:name] == :id, # make "id" column disabled by default
198
+ # :hidden => config[:name] == :id, # hide "id" column by default
199
+ :xtype => XTYPE_MAP[type]
200
+ }
201
+
167
202
  end
168
203
 
169
204
  private
@@ -176,6 +211,14 @@ module Netzke
176
211
  :string => :text_field
177
212
  }
178
213
 
214
+ XTYPE_MAP = {
215
+ :integer => :numberfield,
216
+ :boolean => :textfield,
217
+ :date => :datefield,
218
+ :datetime => :datefield,
219
+ :string => :textfield
220
+ }
221
+
179
222
  def ext_editor(type)
180
223
  TYPE_EDITOR_MAP[type] || :text_field # fall back to :text_field
181
224
  end
@@ -20,7 +20,7 @@ module Netzke
20
20
  Ext.each(['center', 'west', 'east', 'south', 'north'], function(r){
21
21
  var configName = r+'Config';
22
22
  if (config[configName]){
23
- var regionConfig = config[configName].regionConfig || {};
23
+ var regionConfig = config.regions[r] || {};
24
24
  regionConfig.layout = 'fit';
25
25
  regionConfig.region = r;
26
26
  regionConfig.items = [new Ext.componentCache[config[configName].widgetClassName](config[configName])]
@@ -75,39 +75,28 @@ module Netzke
75
75
  config[:regions] || {}
76
76
  end
77
77
 
78
- # def items
79
- # res = []
80
- # config[:regions].each_pair do |k,v|
81
- # width = v.delete(:width)
82
- # height = v.delete(:height)
83
- # split = v[:split].nil? ? true : v.delete(:split) # split is by default true
84
- # region_config = {
85
- # :region => k,
86
- # :width => @pref["#{k}_width"] || width || 100,
87
- # :height => @pref["#{k}_height"] || height || 100,
88
- # :split => split,
89
- # :layout => v.delete(:layout) || 'fit',
90
- # :id => @id_name + "_#{k}_region"
91
- # }
92
- # region_widget_instance = "Netzke::#{v[:widget_class_name]}".constantize.new(v.merge(:name => "#{id_name}__#{k}"))
93
- # region_config.merge!(v)
94
- # region_config[:items] = ["new Ext.componentCache['#{v[:widget_class_name]}'](#{region_widget_instance.js_config.to_js})".l]
95
- # res << region_config
96
- # end
97
- # res
98
- # end
99
-
100
78
  def region_aggregatees
101
79
  aggregatees.reject{ |k,v| !REGIONS.include?(k) }
102
80
  end
103
81
 
104
- # def js_config
105
- # super.merge(:regional_config => items)
106
- # end
82
+ def js_config
83
+ regions = {}
84
+ REGIONS.each do |r|
85
+ if region_aggr = aggregatees[r]
86
+ regions.merge!(r => region_aggr[:region_config] || {})
87
+ height = persistent_config["#{r}_height"] ||= regions[r][:height] if regions[r][:height]
88
+ width = persistent_config["#{r}_width"] ||= regions[r][:width] if regions[r][:width]
89
+ regions[r].merge!(:height => height)
90
+ regions[r].merge!(:width => width)
91
+ end
92
+ end
93
+ super.merge(:regions => regions)
94
+ end
107
95
 
108
- def interface_resize_region(params)
109
- @pref["#{params[:region_name]}_width"] = params[:new_width].to_i if params[:new_width]
110
- @pref["#{params[:region_name]}_height"] = params[:new_height].to_i if params[:new_height]
96
+ def resize_region(params)
97
+ persistent_config["#{params[:region_name]}_width"] = params[:new_width].to_i if params[:new_width]
98
+ persistent_config["#{params[:region_name]}_height"] = params[:new_height].to_i if params[:new_height]
99
+ {}
111
100
  end
112
101
 
113
102
  protected