extjs_scaffold 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,16 +1,23 @@
1
1
  # ExtjsScaffold
2
2
 
3
- Rails 3.1 Scaffold generator for Extjs 4
3
+ Rails 3.2 Scaffold generator for Extjs 4.1
4
4
 
5
5
  ## Usage
6
6
 
7
7
  ### Install
8
+ 1) Add pagination gem to Gemfile
9
+
10
+ gem "kaminari"
11
+
12
+ or
13
+
14
+ gem "will_paginate", "~> 3.0.0"
8
15
 
9
- 1) Install Sencha Extjs 4 into public
16
+ 2) Install Sencha Extjs 4 into public
10
17
 
11
18
  public/extjs
12
19
 
13
- 2) Add Extjs to app/views/layouts/application.html.erb
20
+ 3) Add Extjs to app/views/layouts/application.html.erb
14
21
 
15
22
  <html>
16
23
  <head>
@@ -28,7 +35,7 @@ Rails 3.1 Scaffold generator for Extjs 4
28
35
  </body>
29
36
  </html>
30
37
 
31
- 3) Add Extjs MVC structure app/assets/javascripts/application.js
38
+ 4) Add Extjs MVC structure app/assets/javascripts/application.js
32
39
 
33
40
  //= require_self
34
41
  //= require_tree ./ux
@@ -39,7 +46,7 @@ Rails 3.1 Scaffold generator for Extjs 4
39
46
  //= require_tree ./controller
40
47
  //= require_tree .
41
48
 
42
- 4) Run the install generator
49
+ 5) Run the install generator
43
50
 
44
51
  rails generate extjs_scaffold:install
45
52
 
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["mwinkler"]
9
9
  s.email = ["mhwinkler@gmail.com"]
10
10
  s.homepage = "https://github.com/mojomaze/extjs_scaffold"
11
- s.summary = "Scaffold Generator for Rails 3.1 and Extjs 4"
12
- s.description = "Scaffold Generator for Rails 3.1 and Sencha Extjs 4"
11
+ s.summary = "Scaffold Generator for Rails 3.2 and Extjs 4.1"
12
+ s.description = "Scaffold Generator for Rails 3.2 and Sencha Extjs 4.1"
13
13
 
14
14
  s.files = `git ls-files`.split("\n")
15
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -23,5 +23,5 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency "cucumber"
24
24
  s.add_development_dependency "cucumber-rails"
25
25
  s.add_development_dependency "aruba", "< 0.4.7"
26
- s.add_runtime_dependency "rails", "~> 3.1.0"
26
+ s.add_runtime_dependency "rails", "~> 3.2.0"
27
27
  end
@@ -13,7 +13,7 @@ Feature: Generate Extjs Install and Scaffold
13
13
  And I append to "Gemfile" with:
14
14
  """
15
15
  gem "haml"
16
- gem "kaminari"
16
+ gem "kaminari", "~> 0.13.0"
17
17
  gem "extjs_renderer", "~> 0.1.0"
18
18
  gem 'extjs_scaffold', :path => '../../../'
19
19
 
@@ -74,6 +74,10 @@ Feature: Generate Extjs Install and Scaffold
74
74
  | app/models/product.rb |
75
75
  | app/views/products/index.html.erb |
76
76
  | test/functional/products_controller_test.rb |
77
+ And I run `rails g scaffold team name:string`
78
+ Then the following files should exist:
79
+ | app/views/products/index.html.erb |
80
+ | test/functional/teams_controller_test.rb |
77
81
  And I append to "Gemfile" with:
78
82
  """
79
83
  gem "rspec", "~> 2.7.0"
@@ -1,3 +1,3 @@
1
1
  module ExtjsScaffold
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -55,10 +55,6 @@ module ExtjsScaffold
55
55
  empty_directory File.join("app/assets/javascripts/ux", "grid")
56
56
  template 'GridPanel.js', File.join('app/assets/javascripts/ux/grid/', 'Panel.js')
57
57
 
58
- #toolbar
59
- empty_directory File.join("app/assets/javascripts/ux", "toolbar")
60
- template 'ScrollingToolbar.js', File.join('app/assets/javascripts/ux/toolbar/', 'Scrolling.js')
61
-
62
58
  #window
63
59
  empty_directory File.join("app/assets/javascripts/ux", "window")
64
60
  template 'EditWindow.js', File.join('app/assets/javascripts/ux/window/', 'EditWindow.js')
@@ -12,11 +12,6 @@ Ext.define('<%= app_name %>.ux.grid.Panel', {
12
12
  */
13
13
  multiSelect: true,
14
14
 
15
- // Use a PagingGridScroller
16
- verticalScrollerType: 'paginggridscroller',
17
- invalidateScrollerOnRefresh: false,
18
- //disableSelection: true,
19
-
20
15
  enableColumnHide: false,
21
16
  enableColumnMove: false,
22
17
  enableColumnResize: false,
@@ -114,17 +109,6 @@ Ext.define('<%= app_name %>.ux.grid.Panel', {
114
109
  items: topitems
115
110
  });
116
111
 
117
- if (!me.hideBottomToolbar) {
118
- toolbars.push({
119
- xtype: 'scrollingtoolbar',
120
- itemId: 'bottomtoolbar',
121
- store: me.store,
122
- dock: 'bottom',
123
- displayInfo: true,
124
- displayReload: me.enableStoreReload
125
- });
126
- }
127
-
128
112
  return toolbars;
129
113
  },
130
114
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @author Adapted from Ext.ux.form.SearchField example
2
+ * @author Ext.ux.form.SearchField example
3
3
  * http://www.sencha.com/
4
4
  * @class App.ux.form.field.SearchField
5
5
  * @extends Ext.form.field.Trigger
@@ -25,80 +25,74 @@
25
25
  */
26
26
  Ext.define('<%= app_name %>.ux.form.field.SearchField', {
27
27
  extend: 'Ext.form.field.Trigger',
28
+
28
29
  alias: 'widget.searchfield',
29
30
 
30
- trigger1Cls: 'x-form-clear-trigger',
31
- trigger2Cls: 'x-form-search-trigger',
31
+ trigger1Cls: Ext.baseCSSPrefix + 'form-clear-trigger',
32
+
33
+ trigger2Cls: Ext.baseCSSPrefix + 'form-search-trigger',
32
34
 
33
- emptyText: '',
34
- width: 180,
35
+ hasSearch : false,
36
+ paramName : 'query',
35
37
 
36
- /**
37
- * @cfg {store} store
38
- * The associated data store to receive query
39
- */
40
- store: '',
38
+ initComponent: function() {
39
+ var me = this;
41
40
 
42
- /**
43
- * @cfg {String} queryParam
44
- * The query param name sent to store
45
- * (defaults to <tt>query</tt>)
46
- */
47
- queryParam: 'query',
41
+ me.callParent(arguments);
42
+ me.on('specialkey', function(f, e){
43
+ if (e.getKey() == e.ENTER) {
44
+ me.onTrigger2Click();
45
+ }
46
+ });
48
47
 
49
- initComponent: function(){
50
- this.callParent(arguments);
51
- this.on('specialkey', this.checkEnterKey, this);
52
- },
48
+ // We're going to use filtering
49
+ me.store.remoteFilter = true;
53
50
 
54
- onRender: function() {
55
- this.callParent(arguments);
56
- this.triggerEl.elements[0].setDisplayed('none');
57
- },
51
+ // Set up the proxy to encode the filter in the simplest way as a name/value pair
58
52
 
59
- // Handle enter key presses, execute the search if the field has a value
60
- checkEnterKey: function(field, e) {
61
- var value = this.getValue();
62
- if (e.getKey() === e.ENTER) {
63
- this.search();
53
+ // If the Store has not been *configured* with a filterParam property, then use our filter parameter name
54
+ if (!me.store.proxy.hasOwnProperty('filterParam')) {
55
+ me.store.proxy.filterParam = me.paramName;
56
+ }
57
+ me.store.proxy.encodeFilters = function(filters) {
58
+ return filters[0].value;
64
59
  }
65
60
  },
66
61
 
67
- onTrigger2Click: function() {
68
- this.search();
69
- },
70
-
71
- onTrigger1Click: function() {
72
- this.clearSearch();
62
+ afterRender: function(){
63
+ this.callParent();
64
+ this.triggerCell.item(0).setDisplayed(false);
73
65
  },
74
66
 
75
- search: function() {
67
+ onTrigger1Click : function(){
76
68
  var me = this;
77
- me.triggerEl.elements[0].setDisplayed('block');
78
- var v = this.getRawValue();
79
- if (v.length < 1){
80
- me.clearSearch();
81
- return;
82
- }
83
- if (me.store) {
84
- var query = {}
85
- query[me.queryParam] = v;
86
- Ext.apply(me.store.proxy.extraParams, query);
87
- me.store.load();
69
+
70
+ if (me.hasSearch) {
71
+ me.setValue('');
72
+ me.store.clearFilter();
73
+ me.hasSearch = false;
74
+ me.triggerCell.item(0).setDisplayed(false);
75
+ me.updateLayout();
88
76
  }
89
- me.doComponentLayout();
90
77
  },
91
78
 
92
- clearSearch: function() {
93
- var me = this;
94
- me.triggerEl.elements[0].setDisplayed('none');
95
- me.setValue('');
96
- if (me.store) {
97
- var query = {}
98
- query[me.queryParam] = '';
99
- Ext.apply(me.store.proxy.extraParams, query);
100
- me.store.load();
79
+ onTrigger2Click : function(){
80
+ var me = this,
81
+ store = me.store,
82
+ proxy = store.getProxy(),
83
+ value = me.getValue();
84
+
85
+ if (value.length > 0) {
86
+ // Param name is ignored here since we use custom encoding in the proxy.
87
+ // id is used by the Store to replace any previous filter
88
+ me.store.filter({
89
+ id: me.paramName,
90
+ property: me.paramName,
91
+ value: value
92
+ });
93
+ me.hasSearch = true;
94
+ me.triggerCell.item(0).setDisplayed(true);
95
+ me.updateLayout();
101
96
  }
102
- me.doComponentLayout();
103
97
  }
104
98
  });
@@ -30,13 +30,14 @@ module ExtjsScaffold
30
30
  template "model.rb", "app/models/#{controller_file_name}_tmp.rb"
31
31
  f = File.open "#{destination_root}/app/models/#{controller_file_name}_tmp.rb", "r"
32
32
  model_methods = f.read
33
- # insert after belongs_to or inject
34
- refs = attributes.select{|attr| attr.reference? }.collect{|a| a.name}
33
+ # make related tables updateable - add to attr_accessible
34
+ refs = reference_attributes.map{|a| ":#{a.name}_id, :#{a.name}_#{reference_field(a)}"}
35
35
  if refs.size > 0
36
- insert_into_file "app/models/#{singular_table_name}.rb", model_methods, :after => "belongs_to :#{refs.last}"
37
- else
38
- inject_into_class "app/models/#{singular_table_name}.rb", singular_table_name.capitalize, model_methods
36
+ refs_attr = refs.sort.join(", ")
37
+ insert_into_file "app/models/#{singular_table_name}.rb", ", "+refs_attr, :after => /attr_accessible.*/
39
38
  end
39
+ # add search with pagination class method
40
+ insert_into_file "app/models/#{singular_table_name}.rb", "\n"+model_methods, :after => /attr_accessible.*/
40
41
  remove_file "app/models/#{controller_file_name}_tmp.rb"
41
42
  end
42
43
  end
@@ -291,6 +292,29 @@ module ExtjsScaffold
291
292
  def updatefield_width(attribute)
292
293
  return %w(boolean date integer).include?(attribute.type.to_s) ? 275 : 575
293
294
  end
295
+
296
+ private
297
+
298
+ def resource_attributes
299
+ key_value singular_table_name, "{ #{attributes_hash} }"
300
+ end
301
+
302
+ def attributes_hash
303
+ return if accessible_attributes.empty?
304
+
305
+ accessible_attributes.map do |a|
306
+ name = a.name
307
+ key_value name, "@#{singular_table_name}.#{name}"
308
+ end.sort.join(', ')
309
+ end
310
+
311
+ def accessible_attributes
312
+ attributes.reject(&:reference?)
313
+ end
314
+
315
+ def reference_attributes
316
+ attributes.select(&:reference?)
317
+ end
294
318
  end
295
319
  end
296
320
  end
@@ -24,7 +24,7 @@ end
24
24
 
25
25
  test "should create <%= singular_table_name %>" do
26
26
  assert_difference('<%= class_name %>.count') do
27
- post :create, <%= singular_table_name %>: @<%= singular_table_name %>.attributes
27
+ post :create, <%= resource_attributes %>
28
28
  end
29
29
 
30
30
  assert_redirected_to <%= singular_table_name %>_path(assigns(:<%= singular_table_name %>))
@@ -32,7 +32,7 @@ end
32
32
 
33
33
  test "should create <%= singular_table_name %> via xhr json requests" do
34
34
  assert_difference('<%= class_name %>.count') do
35
- xhr :post, :create, <%= singular_table_name %>: @<%= singular_table_name %>.attributes, :format => :json
35
+ xhr :post, :create, <%= resource_attributes %>, :format => :json
36
36
  end
37
37
 
38
38
  json = ActiveSupport::JSON.decode(@response.body)
@@ -55,7 +55,7 @@ end
55
55
  end
56
56
 
57
57
  test "should update <%= singular_table_name %> via xhr json" do
58
- xhr :put, :update, id: @<%= singular_table_name %>.to_param, <%= singular_table_name %>: @<%= singular_table_name %>.attributes, :format => :json
58
+ xhr :put, :update, id: @<%= singular_table_name %>.to_param, <%= resource_attributes %>, :format => :json
59
59
  json = ActiveSupport::JSON.decode(@response.body)
60
60
  assert json['success']
61
61
  assert_equal json['data']['id'], @<%= singular_table_name %>.id
@@ -84,11 +84,6 @@ describe ExtjsScaffold::Generators::InstallGenerator do
84
84
  contains "Ext.define('#{app_name}.ux.grid.Panel', {"
85
85
  end
86
86
  end
87
- directory "toolbar" do
88
- file "Scrolling.js" do
89
- contains "Ext.define('#{app_name}.ux.toolbar.Scrolling', {"
90
- end
91
- end
92
87
  directory "window" do
93
88
  file "EditWindow.js" do
94
89
  contains "Ext.define('#{app_name}.ux.window.EditWindow', {"
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: extjs_scaffold
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - mwinkler
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-01-03 00:00:00 Z
13
+ date: 2012-06-27 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sqlite3
@@ -97,10 +97,10 @@ dependencies:
97
97
  requirements:
98
98
  - - ~>
99
99
  - !ruby/object:Gem::Version
100
- version: 3.1.0
100
+ version: 3.2.0
101
101
  type: :runtime
102
102
  version_requirements: *id008
103
- description: Scaffold Generator for Rails 3.1 and Sencha Extjs 4
103
+ description: Scaffold Generator for Rails 3.2 and Sencha Extjs 4.1
104
104
  email:
105
105
  - mhwinkler@gmail.com
106
106
  executables: []
@@ -133,7 +133,6 @@ files:
133
133
  - lib/generators/extjs_scaffold/install/templates/GridPanel.js
134
134
  - lib/generators/extjs_scaffold/install/templates/ParentComboField.js
135
135
  - lib/generators/extjs_scaffold/install/templates/Rails.js
136
- - lib/generators/extjs_scaffold/install/templates/ScrollingToolbar.js
137
136
  - lib/generators/extjs_scaffold/install/templates/SearchField.js
138
137
  - lib/generators/extjs_scaffold/install/templates/UpdateWindow.js
139
138
  - lib/generators/extjs_scaffold/install/templates/Updateable.js
@@ -236,7 +235,7 @@ rubyforge_project:
236
235
  rubygems_version: 1.8.8
237
236
  signing_key:
238
237
  specification_version: 3
239
- summary: Scaffold Generator for Rails 3.1 and Extjs 4
238
+ summary: Scaffold Generator for Rails 3.2 and Extjs 4.1
240
239
  test_files:
241
240
  - features/scaffold_generator.feature
242
241
  - features/step_definitions/aruba_ext_steps.rb
@@ -1,170 +0,0 @@
1
- /**
2
- * @author Mark H Winkler
3
- * @class App.ux.toolbar.Scrolling
4
- * @extends Ext.toolbar.Toolbar
5
- * <p>Extends toolbar.Toolbar</p>
6
- * <p>Stripped down version of Ext.toolbar.Paging that shows total recs from store</p>
7
- */
8
- Ext.define('<%= app_name %>.ux.toolbar.Scrolling', {
9
- extend: 'Ext.toolbar.Toolbar',
10
- alias: 'widget.scrollingtoolbar',
11
- requires: ['Ext.toolbar.TextItem'],
12
- /**
13
- * @cfg {String} displayMsg
14
- * The paging status message to display
15
- */
16
- displayMsg : 'Total: {0}',
17
- /**
18
- * @cfg {String} emptyMsg
19
- * The message to display when no records are found (defaults to 'No data to display')
20
- */
21
- emptyMsg : 'No data to display',
22
- /**
23
- * @cfg {String} refreshText
24
- * The quicktip text displayed for the Refresh button (defaults to <tt>'Refresh'</tt>).
25
- * <b>Note</b>: quick tips must be initialized for the quicktip to show.
26
- */
27
- refreshText : 'Refresh',
28
- /**
29
- * @cfg {boolean} displayReload
30
- * add reload button to toolbar
31
- */
32
- displayReload: false,
33
-
34
- initComponent : function(){
35
- var me = this;
36
- me.items = [];
37
-
38
- if (me.displayReload) {
39
- me.items.push({
40
- tooltip: 'Refresh',
41
- iconCls: 'x-tbar-loading',
42
- scope: me,
43
- handler: me.reload
44
- });
45
- }
46
-
47
- if (me.displayInfo) {
48
- me.items.push('->');
49
- me.items.push({xtype: 'tbtext', itemId: 'displayItem'});
50
- }
51
-
52
- me.callParent();
53
-
54
- me.on('afterlayout', me.onLoad, me, {single: true});
55
-
56
- me.bindStore(me.store || 'ext-empty-store', true);
57
- },
58
-
59
- // private
60
- updateInfo : function(){
61
- var me = this,
62
- displayItem = me.child('#displayItem'),
63
- store = me.store,
64
- totalCount = store.getTotalCount();
65
-
66
- if (displayItem) {
67
- count = store.getCount();
68
- if (count === 0) {
69
- msg = me.emptyMsg;
70
- } else {
71
- msg = Ext.String.format(
72
- me.displayMsg,
73
- totalCount
74
- );
75
- }
76
- displayItem.setText(msg);
77
- me.doComponentLayout();
78
- }
79
- },
80
-
81
- // private
82
- onLoad : function(){
83
- var me = this;
84
-
85
- if (!me.rendered) {
86
- return;
87
- }
88
- me.updateInfo();
89
- },
90
-
91
- // private
92
- onLoadError : function(){
93
- if (!this.rendered) {
94
- return;
95
- }
96
- this.child('#refresh').enable();
97
- },
98
-
99
- /**
100
- * Refresh the current page, has the same effect as clicking the 'refresh' button.
101
- */
102
- // doRefresh : function(){
103
- // var me = this,
104
- // current = me.store.currentPage;
105
- //
106
- // if (me.fireEvent('beforechange', me, current) !== false) {
107
- // me.store.loadPage(current);
108
- // }
109
- // },
110
-
111
- /**
112
- * Binds the paging toolbar to the specified {@link Ext.data.Store}
113
- * @param {Ext.data.Store} store The store to bind to this toolbar
114
- * @param {Boolean} initial (Optional) true to not remove listeners
115
- */
116
- bindStore : function(store, initial){
117
- var me = this;
118
-
119
- if (!initial && me.store) {
120
- if (store !== me.store && me.store.autoDestroy) {
121
- me.store.destroy();
122
- } else {
123
- me.store.un('load', me.onLoad, me);
124
- me.store.un('exception', me.onLoadError, me);
125
- }
126
- if (!store) {
127
- me.store = null;
128
- }
129
- }
130
- if (store) {
131
- store = Ext.data.StoreManager.lookup(store);
132
- store.on({
133
- scope: me,
134
- load: me.onLoad,
135
- exception: me.onLoadError
136
- });
137
- }
138
- me.store = store;
139
- },
140
-
141
- // private
142
- onDestroy : function(){
143
- this.bindStore(null);
144
- this.callParent();
145
- },
146
-
147
- updateTotal: function(total){
148
- var me = this,
149
- displayItem = me.child('#displayItem');
150
-
151
- if (displayItem) {
152
- count = total;
153
- if (count === 0) {
154
- msg = me.emptyMsg;
155
- } else {
156
- msg = Ext.String.format(
157
- me.displayMsg,
158
- count
159
- );
160
- }
161
- displayItem.setText(msg);
162
- me.doComponentLayout();
163
- }
164
- },
165
-
166
- reload: function() {
167
- var me = this;
168
- me.store.load();
169
- }
170
- });