netzke-basepack 0.12.9 → 1.0.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/CHANGELOG.md +75 -44
  2. data/Gemfile +4 -2
  3. data/LICENSE +2 -6
  4. data/README.md +22 -24
  5. data/javascripts/basepack.js +0 -8
  6. data/javascripts/{columns.js → grid/columns.js} +59 -71
  7. data/javascripts/grid/event_handlers.js +218 -0
  8. data/javascripts/netzkeremotecombo.js +5 -13
  9. data/javascripts/tristate.js +62 -0
  10. data/javascripts/xdatetime.js +8 -37
  11. data/lib/netzke-basepack.rb +3 -2
  12. data/lib/netzke/basepack.rb +1 -1
  13. data/lib/netzke/basepack/action_column.rb +6 -23
  14. data/lib/netzke/basepack/active_record.rb +0 -6
  15. data/lib/netzke/basepack/attr_config.rb +20 -11
  16. data/lib/netzke/basepack/attribute_config.rb +10 -0
  17. data/lib/netzke/basepack/attributes.rb +196 -0
  18. data/lib/netzke/basepack/column_config.rb +47 -39
  19. data/lib/netzke/basepack/columns.rb +127 -97
  20. data/lib/netzke/basepack/data_accessor.rb +7 -48
  21. data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +15 -17
  22. data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +111 -90
  23. data/lib/netzke/basepack/dynamic_tab_panel.rb +3 -5
  24. data/lib/netzke/basepack/dynamic_tab_panel/{javascripts → client}/dynamic_tab_panel.js +6 -5
  25. data/lib/netzke/basepack/field_config.rb +30 -19
  26. data/lib/netzke/basepack/fields.rb +22 -12
  27. data/lib/netzke/basepack/grid_live_search.rb +1 -4
  28. data/lib/netzke/basepack/grid_live_search/{javascripts → client}/grid_live_search.js +9 -7
  29. data/lib/netzke/basepack/item_persistence.rb +3 -3
  30. data/lib/netzke/basepack/item_persistence/events_plugin.rb +8 -10
  31. data/lib/netzke/basepack/paging_form.rb +7 -11
  32. data/lib/netzke/basepack/paging_form/{javascripts → client}/paging_form.js +4 -4
  33. data/lib/netzke/basepack/query_builder.rb +12 -10
  34. data/lib/netzke/basepack/query_builder/{javascripts → client}/query_builder.js +14 -12
  35. data/lib/netzke/basepack/record_form_window.rb +8 -8
  36. data/lib/netzke/basepack/search_panel.rb +4 -6
  37. data/lib/netzke/basepack/search_panel/{javascripts → client}/condition_field.js +13 -16
  38. data/lib/netzke/basepack/search_panel/{javascripts → client}/search_panel.js +7 -7
  39. data/lib/netzke/basepack/search_window.rb +6 -6
  40. data/lib/netzke/basepack/simple_app/{javascripts → client}/statusbar_ext.js +0 -0
  41. data/lib/netzke/basepack/version.rb +1 -1
  42. data/lib/netzke/form/base.rb +166 -0
  43. data/lib/netzke/{basepack/form/javascripts/form.js → form/base/client/base.js} +77 -38
  44. data/lib/netzke/form/base/client/readonly_mode.css +4 -0
  45. data/lib/netzke/{basepack/form/javascripts → form/base/client}/readonly_mode.js +5 -5
  46. data/lib/netzke/form/endpoints.rb +33 -0
  47. data/lib/netzke/form/services.rb +74 -0
  48. data/lib/netzke/grid/actions.rb +52 -0
  49. data/lib/netzke/grid/base.rb +289 -0
  50. data/lib/netzke/{basepack/grid/javascripts → grid/base/client}/advanced_search.js +5 -1
  51. data/lib/netzke/{basepack/grid/javascripts/grid.js → grid/base/client/base.js} +61 -53
  52. data/lib/netzke/{basepack/grid/javascripts → grid/base/client}/extensions.js +19 -13
  53. data/lib/netzke/{basepack/grid/javascripts → grid/base/client}/remember_selection.js +0 -1
  54. data/lib/netzke/grid/client.rb +8 -0
  55. data/lib/netzke/grid/components.rb +55 -0
  56. data/lib/netzke/grid/configuration.rb +72 -0
  57. data/lib/netzke/grid/endpoints.rb +99 -0
  58. data/lib/netzke/grid/permissions.rb +18 -0
  59. data/lib/netzke/grid/services.rb +141 -0
  60. data/lib/netzke/tree/base.rb +173 -0
  61. data/lib/netzke/{basepack/tree/javascripts/tree.js → tree/base/client/base.js} +55 -26
  62. data/lib/netzke/{basepack/tree/javascripts → tree/base/client}/extensions.js +7 -7
  63. data/lib/netzke/tree/endpoints.rb +34 -0
  64. data/lib/netzke/{basepack/viewport.rb → viewport/base.rb} +3 -3
  65. data/lib/netzke/{basepack/window.rb → window/base.rb} +7 -8
  66. data/lib/netzke/window/base/client/base.js +26 -0
  67. data/locales/de.yml +49 -33
  68. data/locales/en.yml +32 -39
  69. data/locales/es.yml +39 -25
  70. data/locales/nl.yml +39 -25
  71. data/locales/ru.yml +38 -25
  72. data/locales/uk.yml +40 -26
  73. data/stylesheets/basepack.css +10 -0
  74. metadata +48 -45
  75. data/javascripts/mixins/grid_event_handlers.js +0 -139
  76. data/lib/netzke/basepack/accordion.rb +0 -45
  77. data/lib/netzke/basepack/active_record/relation_extensions.rb +0 -27
  78. data/lib/netzke/basepack/form.rb +0 -131
  79. data/lib/netzke/basepack/form/endpoints.rb +0 -35
  80. data/lib/netzke/basepack/form/services.rb +0 -74
  81. data/lib/netzke/basepack/form/stylesheets/readonly_mode.css +0 -14
  82. data/lib/netzke/basepack/grid.rb +0 -570
  83. data/lib/netzke/basepack/grid/endpoints.rb +0 -111
  84. data/lib/netzke/basepack/grid/javascripts/edit_in_form.js +0 -51
  85. data/lib/netzke/basepack/grid/services.rb +0 -148
  86. data/lib/netzke/basepack/tab_panel.rb +0 -22
  87. data/lib/netzke/basepack/tab_panel/javascripts/tab_panel.js +0 -11
  88. data/lib/netzke/basepack/tree.rb +0 -269
  89. data/lib/netzke/basepack/window/javascripts/window.js +0 -26
  90. data/lib/netzke/basepack/wrap_lazy_loaded.rb +0 -29
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Client-side code for [Netzke::Form::Base](http://www.rubydoc.info/github/netzke/netzke-basepack/Netzke/Form/Base)
3
+ * @class Netzke.Form.Base
4
+ */
1
5
  {
2
6
  bodyStyle : 'padding:5px 5px 0',
3
7
  autoScroll : true,
@@ -33,35 +37,37 @@
33
37
  // Now let Ext.form.Form do the rest
34
38
  this.callParent(arguments);
35
39
 
36
- if (this.applyOnReturn) {
37
- Ext.each(this.query('field'), function(field) {
38
- field.on('specialkey', function(field, event) {
39
- if (event.getKey() == 13) this.up('form').onApply();
40
- });
40
+ Ext.each(this.query('field'), function(field) {
41
+ field.on('specialkey', function(field, event) {
42
+ if (event.getKey() == 13) this.up('form').netzkeOnApply();
41
43
  });
42
- }
44
+ });
43
45
  },
44
46
 
45
47
  afterRender: function(){
46
48
  this.callParent();
47
49
 
48
50
  // have a record to be displayed?
49
- if (this.record) { this.setFormValues(this.record); }
51
+ if (this.record) { this.netzkeSetFormValues(this.record); }
50
52
 
51
53
  // render in display mode?
52
- if (this.locked || this.readOnly) this.setReadonlyMode(true);
54
+ if (this.locked || this.readOnly) this.netzkeSetReadonlyMode(true);
53
55
  },
54
56
 
55
- onEdit: function(){
56
- this.setReadonlyMode(false);
57
+ netzkeOnEdit: function(){
58
+ this.netzkeSetReadonlyMode(false);
57
59
  },
58
60
 
59
- onCancel: function(){
61
+ netzkeOnCancel: function(){
60
62
  this.getForm().reset();
61
- this.setReadonlyMode(true, true);
63
+ this.netzkeSetReadonlyMode(true, true);
62
64
  },
63
65
 
64
- updateToolbar: function(){
66
+ /**
67
+ * In lockable mode, dynamically updates the toolbar depending on the read-only state.
68
+ * @method netzkeUpdateToolbar
69
+ */
70
+ netzkeUpdateToolbar: function(){
65
71
  var tbar = this.child('toolbar');
66
72
  if (!tbar) return;
67
73
 
@@ -96,7 +102,11 @@
96
102
  tbar.doLayout();
97
103
  },
98
104
 
99
- onApply: function() {
105
+ /**
106
+ * Handler for the `apply` action.
107
+ * @method netzkeOnApply
108
+ */
109
+ netzkeOnApply: function() {
100
110
  if (this.fireEvent('apply', this)) {
101
111
  var values = this.getForm().getValues();
102
112
  for (var fieldName in values) {
@@ -135,9 +145,10 @@
135
145
  // We must use a different approach when the form is multipart, as we can't use the endpoint
136
146
  if (this.getForm().hasUpload()) {
137
147
  this.getForm().submit({ // normal submit
138
- url: this.netzkeEndpointUrl("netzke_submit"),
148
+ url: this.netzkeEndpointUrl("submit"),
139
149
  params: {
140
- data: Ext.encode(values) // here are the correct values that may be different from display values
150
+ data: Ext.encode(values), // here are the correct values that may be different from display values
151
+ configs: Ext.encode(this.netzkeBuildParentConfigs())
141
152
  },
142
153
  failure: function(form, action){
143
154
  var respObj = Ext.decode(action.response.responseText);
@@ -153,27 +164,33 @@
153
164
  scope: this
154
165
  });
155
166
  } else {
156
- this.netzkeSubmit(Ext.apply((this.baseParams || {}), { data:Ext.encode(values) }), function(){ this.setLoading(false); }, this);
167
+ this.server.submit(Ext.apply((this.baseParams || {}), { data:Ext.encode(values) }), function(){ this.setLoading(false); });
157
168
  }
158
169
  }
159
170
  this.fireEvent('afterApply', this);
160
171
  },
161
172
 
162
- // called from the server
163
- onSubmitSuccess: function() {
173
+ /**
174
+ * Called by the server on successful submit.
175
+ * @method netzkeOnSubmitSuccess
176
+ */
177
+ netzkeOnSubmitSuccess: function() {
164
178
  this.fireEvent("submitsuccess");
165
- if (this.mode == "lockable") this.setReadonlyMode(true);
179
+ if (this.mode == "lockable") this.netzkeSetReadonlyMode(true);
166
180
  this.setLoading(false);
167
181
  },
168
182
 
169
- setFormValues: function(values){
183
+ /**
184
+ * Sets form values (including associations).
185
+ * @method netzkeSetFormValues
186
+ */
187
+ netzkeSetFormValues: function(values){
170
188
  var assocValues = values.meta.associationValues || {};
171
189
  for (var assocFieldName in assocValues) {
172
190
 
173
191
  var assocField = this.getForm().getFields().filter('name', assocFieldName).first();
174
192
  if (assocField.isXType('combobox')) {
175
- // HACK: using private property 'store' here!
176
- assocField.store.loadData([[values[assocFieldName], assocValues[assocFieldName]]]);
193
+ assocField.getStore().loadData([[values[assocFieldName], assocValues[assocFieldName]]]);
177
194
  delete assocField.lastQuery; // force loading the store next time user clicks the trigger
178
195
  } else {
179
196
  assocField.setValue(assocValues[assocFieldName]);
@@ -184,42 +201,64 @@
184
201
  this.getForm().setValues(values);
185
202
  },
186
203
 
187
- setReadonlyMode: function(onOff, cancel){
204
+ /**
205
+ * Dynamically changes form's read-only state.
206
+ * @method netzkeSetReadonlyMode
207
+ * @param {Boolean} onOff
208
+ */
209
+ netzkeSetReadonlyMode: function(onOff){
188
210
  if (this.inReadonlyMode == onOff) return;
189
211
  this.getForm().getFields().each(function(i){
190
- if (i.setReadonlyMode) i.setReadonlyMode(onOff);
212
+ if (i.netzkeSetReadonlyMode) i.netzkeSetReadonlyMode(onOff);
191
213
  });
192
214
 
193
215
  // this.getForm().cleanDestroyed(); // because fields inside of composite fields are not auto-cleaned!
194
216
  this.doLayout();
195
217
  this.inReadonlyMode = onOff;
196
- if (this.mode == "lockable") this.updateToolbar();
218
+ if (this.mode == "lockable") this.netzkeUpdateToolbar();
197
219
  },
198
220
 
199
- // recursively extract field names
200
- extractFields: function(items){
221
+ /**
222
+ * Recursively extract field names from `items`.
223
+ * @method netzkeExtractFields
224
+ * @param {Array} items
225
+ */
226
+ netzkeExtractFields: function(items){
201
227
  Ext.each(items, function(i){
202
- if (i.items) {this.extractFields(i.items);}
228
+ if (i.items) {this.netzkeExtractFields(i.items);}
203
229
  else if (i.name) {this.fieldNames.push(i.name);}
204
230
  }, this);
205
231
  },
206
232
 
207
- applyFormErrors: function(errors) {
233
+ /**
234
+ * Called by the server to display varidation errors.
235
+ * @method netzkeApplyFormErrors
236
+ * @param {Array} errors Array of errors as provided by the `submit` endpoint
237
+ */
238
+ netzkeApplyFormErrors: function(errors) {
208
239
  var field;
209
240
  Ext.iterate(errors, function(fieldName, message){
210
241
  fieldName = fieldName.underscore();
211
- if ( field = this.getForm().findField(fieldName) ||
212
- this.getForm().findField(fieldName.replace(/([a-z]+)([0-9])/g, '$1_$2')) ||
213
- this.getForm().getFields().findBy(function(f){ return fieldName == f.getName().replace(/(.+)__.+/g, '$1'); }) ||
214
- this.getForm().getFields().findBy(function(f){
215
- str = f.getName().camelize();
216
- first = str.substring(0,1);
217
- matchingName = (first.toLowerCase()+str.substring(1)).underscore();
242
+ if ( field = this.getForm().findField(fieldName) ||
243
+ this.getForm().findField(fieldName.replace(/([a-z]+)([0-9])/g, '$1_$2')) ||
244
+ this.getForm().getFields().findBy(function(f){ return fieldName == f.getName().replace(/(.+)__.+/g, '$1'); }) ||
245
+ this.getForm().getFields().findBy(function(f){
246
+ str = f.getName().camelize();
247
+ first = str.substring(0,1);
248
+ matchingName = (first.toLowerCase()+str.substring(1)).underscore();
218
249
  return fieldName == matchingName;
219
250
  })
220
251
  ) {
221
252
  field.markInvalid(message.join('<br/>'));
222
253
  }
223
254
  }, this);
224
- }
255
+ },
256
+
257
+ netzkeDisplayFormErrors: function(errors){
258
+ var body = "";
259
+ Ext.each(errors, function(error){
260
+ body += error.msg + "<br/>"
261
+ });
262
+ this.netzkeNotify(body);
263
+ },
225
264
  }
@@ -0,0 +1,4 @@
1
+ input.readonly, textarea.readonly {
2
+ background-color: #f5f5f5;
3
+ background-image: none;
4
+ }
@@ -1,8 +1,8 @@
1
- // Overrides that implement setReadonlyMode for form fields.
1
+ // Overrides that implement netzkeSetReadonlyMode for form fields.
2
2
  //
3
3
 
4
4
  Ext.form.field.Base.override({
5
- setReadonlyMode: function(onOff){
5
+ netzkeSetReadonlyMode: function(onOff){
6
6
  if (this.hidden) return;
7
7
 
8
8
  if (!this.initialConfig.readOnly) {
@@ -21,15 +21,15 @@ Ext.form.field.Base.override({
21
21
 
22
22
  // Also the FieldContainer
23
23
  Ext.form.FieldContainer.override({
24
- setReadonlyMode: function(onOff){
24
+ netzkeSetReadonlyMode: function(onOff){
25
25
  this.items.each(function(i){
26
- i.setReadonlyMode(onOff);
26
+ i.netzkeSetReadonlyMode(onOff);
27
27
  });
28
28
  }
29
29
  });
30
30
 
31
31
  Ext.form.field.Checkbox.override({
32
- setReadonlyMode: function(onOff){
32
+ netzkeSetReadonlyMode: function(onOff){
33
33
  this.setDisabled(onOff);
34
34
  }
35
35
  });
@@ -0,0 +1,33 @@
1
+ module Netzke
2
+ module Form
3
+ module Endpoints
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ # Called when the form gets submitted (e.g. by pressing the Apply button)
8
+ endpoint :submit do |params|
9
+ data = ActiveSupport::JSON.decode(params[:data])
10
+ submit(data, client)
11
+ end
12
+
13
+ # Can be called when the form needs to load a record with given ID. E.g.:
14
+ #
15
+ # someForm.server.load({id: 100});
16
+ endpoint :load do |params|
17
+ @record = model && model_adapter.find_record(params[:id])
18
+ client.netzke_set_form_values js_record_data
19
+ end
20
+
21
+ # Returns options for a combobox
22
+ # params receive:
23
+ # +attr+ - column's name
24
+ # +query+ - what's typed-in in the combobox
25
+ # +id+ - selected record id
26
+ endpoint :get_combobox_options do |params|
27
+ attr = fields[params[:attr].to_sym]
28
+ client.data = model_adapter.combo_data(attr, params[:query])
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,74 @@
1
+ module Netzke
2
+ module Form
3
+ module Services
4
+ extend ActiveSupport::Concern
5
+
6
+ def submit(data, client)
7
+ # File uploads are in raw params instead of "data" hash, so, mix them in into "data"
8
+ controller.params.each_pair do |k,v|
9
+ data[k] = v if v.is_a?(ActionDispatch::Http::UploadedFile)
10
+ end
11
+
12
+ success = create_or_update_record(data)
13
+
14
+ if success
15
+ client.netzke_set_form_values(js_record_data)
16
+ client.success = true # respond to classic form submission with {success: true}
17
+ client.netzke_on_submit_success # inform the Netzke endpoint caller about success
18
+ else
19
+ errors = model_adapter.errors_array(@record).map do |error|
20
+ {level: :error, msg: error}
21
+ end
22
+ client.netzke_display_form_errors(errors)
23
+ client.netzke_apply_form_errors(build_form_errors(record))
24
+ end
25
+ end
26
+
27
+ def values
28
+ record && record.netzke_hash(fields)
29
+ end
30
+
31
+ private
32
+
33
+ # Builds the form errors
34
+ def build_form_errors(record)
35
+ form_errors = {}
36
+ foreign_keys = model_adapter.hash_fk_model
37
+ record.errors.to_hash.map{|field, error|
38
+ # some ORM return an array for error
39
+ error = error.join ', ' if error.kind_of? Array
40
+ # Get the correct field name for the errors on foreign keys
41
+ if foreign_keys.has_key?(field)
42
+ fields.each do |k, v|
43
+ # Hack to stop to_nifty_json from camalizing model__field
44
+ field = k.to_s.gsub('__', '____') if k.to_s.split('__').first == foreign_keys[field].to_s
45
+ end
46
+ end
47
+ form_errors[field] ||= []
48
+ form_errors[field] << error
49
+ }
50
+ form_errors
51
+ end
52
+
53
+ # Creates/updates a record from hash
54
+ def create_or_update_record(hsh)
55
+ hsh.merge!(config[:strong_values]) if config[:strong_values]
56
+
57
+ # only pick the record specified in the params if it was not provided in the configuration
58
+ @record ||= model_adapter.find_record hsh.delete(model.primary_key.to_s)
59
+
60
+ #model.find(:first, :conditions => model.primary_key => hsh.delete(model.primary_key)})
61
+ success = true
62
+
63
+ @record = model.new if @record.nil?
64
+
65
+ hsh.each_pair do |k,v|
66
+ model_adapter.set_record_value_for_attribute(@record, fields[k.to_sym].nil? ? {:name => k} : fields[k.to_sym], v)
67
+ end
68
+
69
+ # did we have complete success?
70
+ success && model_adapter.save_record(@record)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,52 @@
1
+ module Netzke
2
+ module Grid
3
+ module Actions
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ action :add do |a|
8
+ a.icon = :add
9
+ end
10
+
11
+ action :edit do |a|
12
+ a.disabled = true # initial
13
+ a.icon = :table_edit
14
+ end
15
+
16
+ action :delete do |a|
17
+ a.disabled = true # initial
18
+ a.icon = :table_row_delete
19
+ end
20
+
21
+ action :apply do |a|
22
+ a.icon = :tick
23
+ end
24
+
25
+ action :search do |a|
26
+ a.enable_toggle = true
27
+ a.icon = :magnifier
28
+ end
29
+ end
30
+
31
+ def has_add_action?
32
+ allowed_to?(:create)
33
+ end
34
+
35
+ def has_edit_action?
36
+ allowed_to?(:update)
37
+ end
38
+
39
+ def has_apply_action?
40
+ config.edit_inline && (allowed_to?(:create) || allowed_to?(:update))
41
+ end
42
+
43
+ def has_delete_action?
44
+ allowed_to?(:delete)
45
+ end
46
+
47
+ def has_search_action?
48
+ true
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,289 @@
1
+ module Netzke
2
+ module Grid
3
+ # Ext.grid.Panel-based component with the following features:
4
+ #
5
+ # * infinite scrolling or pagination
6
+ # * automatic default attribute configuration (overridable via config)
7
+ # * multi-line CRUD operations
8
+ # * adding/editing records via a form
9
+ # * editing multiple records simultaneously
10
+ # * one-to-many association support
11
+ # * server-side sorting and filtering
12
+ # * permissions
13
+ # * persistent column resizing, moving and toggling
14
+ # * complex query search with preset management
15
+ #
16
+ # Client-side methods are documented here: http://api.netzke.org/client/classes/Netzke.Grid.Base.html.
17
+ #
18
+ # == Configuration
19
+ #
20
+ # The following config options are supported:
21
+ #
22
+ # [model]
23
+ #
24
+ # Name of the ActiveRecord model that provides data to this Grid (e.g. "User") or the model's class (e.g. User).
25
+ # Required.
26
+ #
27
+ # [columns]
28
+ #
29
+ # Explicit list of columns to be displayed in the grid; each column may be represented by a symbol (attribute name),
30
+ # or a hash, which contains the +name+ key pointing to the attribute name and additional configuration keys (see
31
+ # the "Configuring attributes" section below). For example:
32
+ #
33
+ # class Users < Netzke::Grid::Base
34
+ # def configure(c)
35
+ # super
36
+ # c.model = User
37
+ # c.columns = [
38
+ # :first_name,
39
+ # :last_name,
40
+ # { name: :salary, with: 50 }
41
+ # ]
42
+ # end
43
+ # end
44
+ #
45
+ # Defaults to model attribute list.
46
+ #
47
+ # Note, that you can also individually override column configs (e.g. setting a column's width) by using the
48
+ # +column+ DSL method (see +Basepack::Columns+), and override attributes (e.g. making an attribute read-only) by
49
+ # using the +attribute+ DSL method (see +Basepack::Attributes+).
50
+ #
51
+ # [form_items]
52
+ #
53
+ # Array of form items. This may define arbitrary form layout. An item that represents a specific attribute, should
54
+ # be specified as either a symbol (attribute name), or a hash containing the +name+ key pointing to the attribute
55
+ # name, as well as additional configuration keys.
56
+ #
57
+ # class Users < Netzke::Basepack::Grid
58
+ # def configure(c)
59
+ # super
60
+ # c.model = User
61
+ # c.form_items = [
62
+ # {
63
+ # xtype: 'fieldset', title: 'Name', items: [:first_name, :last_name]
64
+ # },
65
+ # { name: :salary, disabled: true }
66
+ # ]
67
+ # end
68
+ # end
69
+ #
70
+ # Defaults to model attribute list.
71
+ #
72
+ # [attribute_overrides]
73
+ #
74
+ # Hash of per-attribute configurations. This allows overriding attributes configs that will be reflected by both
75
+ # corresponding grid column and form field.
76
+ #
77
+ # Using this option may be convenient when building composite components containing multiple grids. From inside a
78
+ # given grid class it's easier to use the +attribute+ DSL method (see "Configuring attributes").
79
+ #
80
+ # [scope]
81
+ #
82
+ # A Proc object used to scope out grid data. Receives the current relation as a parameter and must return the
83
+ # modified relation. For example:
84
+ #
85
+ # class Books < Netzke::Basepack::Grid
86
+ # def configure(c)
87
+ # c.model = "Book"
88
+ # super
89
+ # c.scope = lambda {|r| r.where(author_id: 1) }
90
+ # end
91
+ # end
92
+ #
93
+ # [strong_values]
94
+ #
95
+ # A hash of attributes to be merged atop of every created/updated record, e.g. +role_id: 1+
96
+ #
97
+ # [edit_inline]
98
+ # Whether record editing should happen inline (as opposed to using a form). When set to +true+, automatically sets
99
+ # +paging+ to +true+. Defaults to +false+.
100
+ #
101
+ # [context_menu]
102
+ #
103
+ # An array of actions (e.g. [:edit, "-", :delete] - see the Actions section) or +false+ to disable the context menu.
104
+ #
105
+ # [paging]
106
+ #
107
+ # Set to +true+ to use pagination instead of infinite scrolling. Is automatically set to
108
+ # +true+ if +edit_inline+ is +true+. Defaults to +false+.
109
+ #
110
+ # [store_config]
111
+ #
112
+ # Extra configuration for the JS class's internal store (Ext.data.ProxyStore), which will override Netzke's
113
+ # defaults. For example, to modify amount of records per page (defaults to 25), do:
114
+ #
115
+ # def configure(c)
116
+ # c.paging = true
117
+ # c.store_config = {page_size: 100}
118
+ # super
119
+ # end
120
+ #
121
+ # Another example, enable (multi) sorting initially:
122
+ #
123
+ # def configure(c)
124
+ # c.store_config = {sorters: [:title, {property: :author__first_name, direction: :DESC}]}
125
+ # super
126
+ # end
127
+ #
128
+ # [disable_dirty_page_warning]
129
+ #
130
+ # Do not warn the user about dirty records on the page when changing the page. Defaults to +false+.
131
+ #
132
+ # [permissions]
133
+ #
134
+ # Hash that can have a combination of the following boolean keys: +create+, +read+, +update+, +delete+ that
135
+ # set corresponding permissions on the grid. For example, to disable deleting records:
136
+ #
137
+ # c.permissions = {delete: false}
138
+ #
139
+ # == Configuring attributes (columns and form fields)
140
+ #
141
+ # === Overriding individual attributes
142
+ #
143
+ # To override configuration for a specific attribute, you may either use the +attribute_overrides+ configuration
144
+ # option (see above), or the +attribute+ DSL method, for example:
145
+ #
146
+ # class Books < Netzke::Grid::Base
147
+ # attribute :price do |c|
148
+ # c.read_only = true
149
+ # end
150
+ #
151
+ # def configure(c)
152
+ # c.model = Book
153
+ # super
154
+ # end
155
+ # end
156
+ #
157
+ # This will make the 'price' column (as well as corresponding form field) read-only.
158
+ #
159
+ # The same DSL method may be used for defining virtual attributes. For details, refer to +Basepack::Attributes+.
160
+ #
161
+ # === Overriding individual column settings
162
+ #
163
+ # To override configuration for a column (like making the column hidden or specyfing its initial width), either add
164
+ # the +column_config+ key to the +attribute_overrides+ (see above), or use the +column+ DSL method, for example:
165
+ #
166
+ # column :full_name do |c|
167
+ # c.width = 200
168
+ # end
169
+ #
170
+ # For details, refer to +Basepack::Columns+.
171
+ #
172
+ # === Specifying column list
173
+ #
174
+ # To explicitely specify columns in the grid, use the +columns+ config option, or override +Grid#columns+:
175
+ #
176
+ # def columns
177
+ # super + [:extra_column]
178
+ # end
179
+ #
180
+ # == One-to-many association support
181
+ #
182
+ # If the model bound to a grid +belongs_to+ another model, Grid can display an "assocition column" - where the user
183
+ # can select the associated record from a drop-down box. You can specify which method of the association should be
184
+ # used as the display value for the drop-down box options by using the double-underscore notation on the column
185
+ # name, where the association name is separated from the association method by "__" (double underscore). For
186
+ # example, let's say we have a Book that +belongs_to+ model Author, and Author responds to +first_name+. This way,
187
+ # the book grid can have a column defined as follows:
188
+ #
189
+ # {name: "author__first_name"}
190
+ #
191
+ # Grid will detect it to be an association column, and will use the drop-down box for selecting an author, where the
192
+ # list of authors will be represented by the author's first name.
193
+ #
194
+ # In order to scope out the records displayed in the drop-down box, the +scope+ column option can be used, e.g.:
195
+ #
196
+ # {name: "author__first_name", scope: lambda {|relation| relation.where(popular: true).limit(10)}
197
+ #
198
+ # == Add/Edit forms
199
+ #
200
+ # Add/Edit forms are each wrapped in a separate +Window::Base+-descending component (called +RecordFormWindow+
201
+ # for the add/edit forms, and can be overridden individually as any other child component.
202
+ #
203
+ # === Overriding form windows
204
+ #
205
+ # Override the following direct child components to change the looks of the pop-up windows: +:add_window+,
206
+ # +:edit_window+, +:multiedit_window+, and +:search_window+. For example, to override the title of the Add form,
207
+ # do:
208
+ #
209
+ # component :add_window do |c|
210
+ # super c
211
+ # c.title = "Adding new record"
212
+ # c.width = "90%"
213
+ # end
214
+ #
215
+ # === Modifying forms
216
+ #
217
+ # The forms will by default display the fields that correspond to the configured columns, taking over meaningful
218
+ # configuration options (e.g. +text+ will be converted into +fieldLabel+).
219
+ # You may override the default fields displayed in the all add/edit forms by overriding the
220
+ # +default_form_items+ method, which should return an array understood by the +items+ config property of the
221
+ # +Form+. If you need to use a custom +Form::Base+-descending class instead of +Form+, you need to override the
222
+ # +configure_form_window+ method:
223
+ #
224
+ # def configure_form_window(c)
225
+ # super
226
+ # c.form_config.klass = UserForm
227
+ # end
228
+ #
229
+ # To individually override forms, you should override the wrapping window components, as shown in the previous
230
+ # session. E.g., to modify the set of fields in the Add form:
231
+ #
232
+ # component :add_window do |c|
233
+ # super c
234
+ # c.form_config.items = [:title]
235
+ # end
236
+ #
237
+ # == Actions
238
+ #
239
+ # You can override Grid's actions to change their text, icons, and tooltips (see
240
+ # http://rdoc.info/github/netzke/netzke-core/Netzke/Core/Actions).
241
+ #
242
+ # Grid implements the following actions:
243
+ #
244
+ # [add]
245
+ #
246
+ # Add record
247
+ #
248
+ # [delete]
249
+ #
250
+ # Delete record(s)
251
+ #
252
+ # [edit]
253
+ #
254
+ # Edit record(s)
255
+ #
256
+ # [apply]
257
+ #
258
+ # Applying inline changes (after inline adding/editing of record)
259
+ #
260
+ # [search]
261
+ #
262
+ # Show advanced search query builder
263
+ class Base < Netzke::Base
264
+ include Netzke::Grid::Configuration
265
+ include Netzke::Grid::Endpoints
266
+ include Netzke::Grid::Services
267
+ include Netzke::Grid::Actions
268
+ include Netzke::Grid::Components
269
+ include Netzke::Grid::Permissions
270
+ include Netzke::Grid::Client
271
+ include Netzke::Basepack::Attributes
272
+ include Netzke::Basepack::Columns
273
+ include Netzke::Basepack::DataAccessor
274
+
275
+ client_class do |c|
276
+ c.extend = "Ext.grid.Panel"
277
+ c.include :advanced_search
278
+ c.include :remember_selection
279
+
280
+ c.mixins << "Netzke.Grid.Columns"
281
+ c.mixins << "Netzke.Grid.EventHandlers"
282
+
283
+ c.translate :are_you_sure, :confirmation, :proceed_with_unapplied_changes
284
+
285
+ c.require :extensions
286
+ end
287
+ end
288
+ end
289
+ end