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
@@ -20,7 +20,7 @@
20
20
  },
21
21
 
22
22
  buildFormFromQuery: function(query) {
23
- this.onClearAll();
23
+ this.netzkeOnClearAll();
24
24
 
25
25
  if (query.length !== 0) {
26
26
  Ext.each(query, function(f, i){
@@ -82,20 +82,22 @@
82
82
  }, this);
83
83
  },
84
84
 
85
- onClearAll: function() {
85
+ netzkeOnClearAll: function() {
86
86
  this.removeAllTabs(true);
87
- this.getActiveTab().items.first().onClearAll();
87
+ this.getActiveTab().items.first().netzkeOnClearAll();
88
88
  },
89
89
 
90
- onReset: function() {
91
- this.eachTab(function(t) { t.onReset(); });
90
+ netzkeOnReset: function() {
91
+ this.eachTab(function(t) {
92
+ t.items.first().onReset();
93
+ });
92
94
  },
93
95
 
94
96
  removeAllTabs: function(exceptLast) {
95
97
  this.eachTab(function(t) { if (this.items.getCount() > (exceptLast ? 2 : 1)) {this.remove(t);} }, this);
96
98
  },
97
99
 
98
- onSavePreset: function(){
100
+ netzkeOnSavePreset: function(){
99
101
  var searchName = this.presetsCombo.getRawValue();
100
102
 
101
103
  if (searchName !== "") {
@@ -103,7 +105,7 @@
103
105
  var existingPresetIndex = presetsComboStore.find('text', searchName);
104
106
  if (existingPresetIndex !== -1) {
105
107
  // overwriting
106
- Ext.Msg.confirm(this.i18n.overwriteConfirmTitle, this.i18n.overwriteConfirm, function(btn, text){
108
+ Ext.Msg.confirm(this.i18n.overwriteConfirmTitle, Ext.String.format(this.i18n.overwriteConfirm, searchName), function(btn, text){
107
109
  if (btn == 'yes') {
108
110
  var r = presetsComboStore.getAt(existingPresetIndex);
109
111
  r.set('value', this.getQuery(true));
@@ -119,19 +121,19 @@
119
121
  },
120
122
 
121
123
  doSavePreset: function(name){
122
- this.savePreset({
124
+ this.server.savePreset({
123
125
  name: name,
124
126
  query: Ext.encode(this.getQuery(true))
125
127
  });
126
128
  },
127
129
 
128
- onDeletePreset: function(){
130
+ netzkeOnDeletePreset: function(){
129
131
  var searchName = this.presetsCombo.getRawValue();
130
132
  if (searchName !== "") {
131
- Ext.Msg.confirm(this.i18n.deleteConfirmTitle, this.i18n.overwriteConfirm, function(btn, text){
133
+ Ext.Msg.confirm(this.i18n.deleteConfirmTitle, Ext.String.format(this.i18n.deleteConfirm, searchName), function(btn, text){
132
134
  if (btn == 'yes') {
133
135
  this.removePresetFromList(searchName);
134
- this.deletePreset({
136
+ this.server.deletePreset({
135
137
  name: searchName
136
138
  });
137
139
  }
@@ -139,7 +141,7 @@
139
141
  }
140
142
  },
141
143
 
142
- onApply: function() {
144
+ netzkeOnApply: function() {
143
145
  this.fireEvent('conditionsupdate', this.getQuery());
144
146
  },
145
147
 
@@ -1,6 +1,6 @@
1
1
  module Netzke
2
2
  module Basepack
3
- class RecordFormWindow < Netzke::Basepack::Window
3
+ class RecordFormWindow < Netzke::Window::Base
4
4
  def configure(c)
5
5
  super
6
6
  c.fbar = [:ok, :cancel]
@@ -15,12 +15,12 @@ module Netzke
15
15
  c.record_id = config.client_config[:record_id]
16
16
  end
17
17
 
18
- component :multi_edit_form do |c|
18
+ component :multiedit_form do |c|
19
19
  preconfigure_form(c)
20
- c.multi_edit = true
20
+ c.multiedit = true
21
21
  end
22
22
 
23
- js_configure do |c|
23
+ client_class do |c|
24
24
  c.button_align = :right
25
25
  c.width = '80%'
26
26
  c.auto_height = true
@@ -32,13 +32,13 @@ module Netzke
32
32
  }
33
33
  JS
34
34
 
35
- c.on_ok = <<-JS
35
+ c.netzke_on_ok = <<-JS
36
36
  function(params){
37
- this.items.first().onApply();
37
+ this.items.first().netzkeOnApply();
38
38
  }
39
39
  JS
40
40
 
41
- c.on_cancel = <<-JS
41
+ c.netzke_on_cancel = <<-JS
42
42
  function(params){
43
43
  this.close();
44
44
  }
@@ -56,7 +56,7 @@ module Netzke
56
56
  end
57
57
 
58
58
  def preconfigure_form(c)
59
- c.klass = Form
59
+ c.klass = Netzke::Form::Base
60
60
  c.border = true
61
61
  c.bbar = false
62
62
  c.prevent_header = true
@@ -39,16 +39,15 @@ module Netzke
39
39
  ATTRIBUTE_OPERATORS_MAP[:decimal] = ATTRIBUTE_OPERATORS_MAP[:integer]
40
40
  ATTRIBUTE_OPERATORS_MAP[:float] = ATTRIBUTE_OPERATORS_MAP[:integer]
41
41
 
42
- js_configure do |c|
42
+ client_class do |c|
43
43
  c.extend = "Ext.form.FormPanel"
44
44
  c.padding = 5
45
45
  c.auto_scroll = true
46
46
  c.require :condition_field
47
- c.mixin
48
47
  c.attribute_operators_map = ATTRIBUTE_OPERATORS_MAP
49
48
  end
50
49
 
51
- def js_configure(c)
50
+ def configure_client(c)
52
51
  super
53
52
  c.attrs = config[:fields]
54
53
  c.preset_query = (config[:load_last_preset] ? last_preset.try(:fetch, "query") : config[:query]) || []
@@ -56,15 +55,14 @@ module Netzke
56
55
 
57
56
  def attributes
58
57
  config[:fields].map do |f|
59
- f[:attr_type] ||= :string
60
- {name: f[:name], field_label: f[:field_label], attr_type: f[:attr_type]}
58
+ f[:type] ||= :string
59
+ {name: f[:name], field_label: f[:field_label], type: f[:type]}
61
60
  end
62
61
  end
63
62
 
64
63
  def last_preset
65
64
  (state[:presets] || []).last
66
65
  end
67
-
68
66
  end
69
67
  end
70
68
  end
@@ -1,4 +1,4 @@
1
- Ext.define('Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField', {
1
+ Ext.define('Netzke.Basepack.SearchPanel.ConditionField', {
2
2
  extend: 'Ext.form.FieldContainer',
3
3
  alias: 'widget.netzkebasepacksearchpanelconditionfield',
4
4
 
@@ -22,12 +22,12 @@ Ext.define('Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField', {
22
22
  },
23
23
 
24
24
  initComponent: function(){
25
- if (!this.attrType || this.assoc) this.attrType = 'string';
25
+ if (!this.type || this.assoc) this.type = 'string';
26
26
 
27
- this.attrTypeHash = {};
27
+ this.typeHash = {};
28
28
 
29
29
  var storeData = Ext.Array.map(this.ownerCt.attrs, function(attr) {
30
- this.attrTypeHash[attr.name] = attr.attrType;
30
+ this.typeHash[attr.name] = attr.type;
31
31
  return [attr.name, attr.text];
32
32
  }, this);
33
33
 
@@ -44,7 +44,7 @@ Ext.define('Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField', {
44
44
  triggerAction: 'all',
45
45
  value: this.attr ? this.attr.underscore() : "",
46
46
  listeners: {
47
- select: this.onAttributeChange,
47
+ select: this.netzkeOnAttributeChange,
48
48
  scope: this
49
49
  }
50
50
  }
@@ -52,9 +52,9 @@ Ext.define('Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField', {
52
52
 
53
53
  if (this.attr) {
54
54
 
55
- var operators = this.ownerCt.attributeOperatorsMap[this.attrType] || [[]];
55
+ var operators = this.ownerCt.attributeOperatorsMap[this.type] || [[]];
56
56
 
57
- if (this.attrType === 'boolean') {
57
+ if (this.type === 'boolean') {
58
58
  items.push({
59
59
  xtype : 'tricheckbox',
60
60
  width: 100,
@@ -95,7 +95,7 @@ Ext.define('Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField', {
95
95
  value: this.value,
96
96
  itemId: "valueField"
97
97
  },
98
- this.valueFieldConfigs[this.attrType] // refining the config dependent on the attr type
98
+ this.valueFieldConfigs[this.type] // refining the config dependent on the attr type
99
99
  ));
100
100
  }
101
101
 
@@ -111,9 +111,6 @@ Ext.define('Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField', {
111
111
 
112
112
  this.items = items;
113
113
 
114
- // Why on Earth is this not working? Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField undefined???
115
- // Netzke.classes.Basepack.SearchPanel.ConditionField.superclass.initComponent.call(this);
116
- // Ext.form.CompositeField.prototype.initComponent.call(this); // workaround
117
114
  this.callParent();
118
115
 
119
116
  this.attrCombo = this.getComponent('attrCombo');
@@ -131,24 +128,24 @@ Ext.define('Netzke.classes.Netzke.Basepack.SearchPanel.ConditionField', {
131
128
  ownerCt.fireEvent('fieldsnumberchange');
132
129
  },
133
130
 
134
- onAttributeChange: function(e){
131
+ netzkeOnAttributeChange: function(e){
135
132
  this.fireEvent('configured');
136
133
  this.changeAttribute(e.value);
137
134
  },
138
135
 
139
- // Dynamically replace self with a field with different attrType
136
+ // Dynamically replace self with a field with different type
140
137
  changeAttribute: function(attr){
141
- var attrType = this.attrTypeHash[attr];
138
+ var type = this.typeHash[attr];
142
139
  var idx = this.ownerCt.items.indexOf(this);
143
140
  var owner = this.ownerCt;
144
- var newSelf = Ext.createByAlias('widget.netzkebasepacksearchpanelconditionfield', Ext.apply(this.initialConfig, {name: attr, attrType: attrType, attr: attr.underscore(), ownerCt: this.ownerCt, operator: null}));
141
+ var newSelf = Ext.createByAlias('widget.netzkebasepacksearchpanelconditionfield', Ext.apply(this.initialConfig, {name: attr, type: type, attr: attr.underscore(), ownerCt: this.ownerCt, operator: null}));
145
142
  owner.insert(idx, newSelf);
146
143
  setTimeout(function() { this.destroy(); }.bind(this), 1); // this gives time for pending events to get handled without errors
147
144
  },
148
145
 
149
146
  // Returns true if it should be in the query
150
147
  valueIsSet: function(){
151
- return !!(this.attrCombo.getValue() && (this.attrType === 'boolean' || this.operatorCombo.getValue()) && !Ext.isEmpty(this.valueField.getValue()));
148
+ return !!(this.attrCombo.getValue() && (this.type === 'boolean' || this.operatorCombo.getValue()) && !Ext.isEmpty(this.valueField.getValue()));
152
149
  },
153
150
 
154
151
  // Returns the query object
@@ -3,13 +3,13 @@
3
3
  this.callParent();
4
4
  this.buildFormFromQuery(this.presetQuery);
5
5
 
6
- this.onAddCondition();
6
+ this.netzkeOnAddCondition();
7
7
 
8
8
  },
9
9
 
10
10
  // Will probably need to be performance-optimized in the future, as recreating the fields is expensive
11
11
  buildFormFromQuery: function(query) {
12
- this.onClearAll();
12
+ this.netzkeOnClearAll();
13
13
  Ext.each(query, function(f){
14
14
  f.ownerCt = this;
15
15
  this.insert(this.items.length - 1, Ext.createByAlias('widget.netzkebasepacksearchpanelconditionfield', f));
@@ -17,23 +17,23 @@
17
17
  this.doLayout();
18
18
  },
19
19
 
20
- onAddCondition: function() {
20
+ netzkeOnAddCondition: function() {
21
21
  var condField = Ext.createByAlias('widget.netzkebasepacksearchpanelconditionfield', {ownerCt: this});
22
22
  condField.on('configured', function() {
23
- this.onAddCondition();
23
+ this.netzkeOnAddCondition();
24
24
  }, this, {single: true});
25
25
  this.add(condField);
26
26
  this.doLayout();
27
27
  this.fireEvent('fieldsnumberchange');
28
28
  },
29
29
 
30
- onReset: function() {
30
+ netzkeOnReset: function() {
31
31
  this.items.each(function(f){
32
32
  if (f.valueField) {f.clearValue();}
33
33
  });
34
34
  },
35
35
 
36
- onClearAll: function() {
36
+ netzkeOnClearAll: function() {
37
37
  this.eachConfiguredField(function(f) {
38
38
  this.remove(f);
39
39
  }, this);
@@ -56,7 +56,7 @@
56
56
  this.eachConfiguredField(function(f){
57
57
  if (f.valueIsSet() || all) {
58
58
  var cond = f.buildValue();
59
- if (all) {cond.attrType = f.attrType;}
59
+ if (all) {cond.type = f.type;}
60
60
  query.push(cond);
61
61
  }
62
62
  });
@@ -1,11 +1,11 @@
1
1
  module Netzke
2
2
  module Basepack
3
- class SearchWindow < Netzke::Basepack::Window
3
+ class SearchWindow < Netzke::Window::Base
4
4
 
5
5
  action :search
6
6
  action :cancel
7
7
 
8
- js_configure do |c|
8
+ client_class do |c|
9
9
  c.width = "50%"
10
10
  c.auto_height = true
11
11
  c.close_action = "hide"
@@ -26,14 +26,14 @@ module Netzke
26
26
  }
27
27
  JS
28
28
 
29
- c.on_search = <<-JS
29
+ c.netzke_on_search = <<-JS
30
30
  function(){
31
31
  this.closeRes = 'search';
32
32
  this.hide();
33
33
  }
34
34
  JS
35
35
 
36
- c.on_cancel = <<-JS
36
+ c.netzke_on_cancel = <<-JS
37
37
  function(){
38
38
  this.hide();
39
39
  }
@@ -42,14 +42,14 @@ module Netzke
42
42
 
43
43
  def configure(c)
44
44
  super
45
- c.items = [:search_panel]
45
+ c.items = [:query_builder]
46
46
  c.title = I18n.t('netzke.basepack.search_window.title')
47
47
  c.persistence = false
48
48
  c.prevent_header = true
49
49
  c.buttons = [:search, :cancel]
50
50
  end
51
51
 
52
- component :search_panel do |c|
52
+ component :query_builder do |c|
53
53
  c.klass = QueryBuilder
54
54
  c.model = config[:model]
55
55
  c.fields = config[:fields]
@@ -1,5 +1,5 @@
1
1
  module Netzke
2
2
  module Basepack
3
- VERSION = "0.12.9"
3
+ VERSION = "1.0.0.0.pre"
4
4
  end
5
5
  end
@@ -0,0 +1,166 @@
1
+ module Netzke
2
+ module Form
3
+ # Ext.form.Panel-based component with the following features
4
+ #
5
+ # * automatic default attribute configuration (overridable via config)
6
+ # * model validations
7
+ # * dynamic loading of form data
8
+ # * lockable mode
9
+ #
10
+ # Client-side methods are documented here: http://api.netzke.org/client/classes/Netzke.Form.Base.html.
11
+ #
12
+ # == Configuration
13
+ #
14
+ # [model]
15
+ #
16
+ # Name of the ActiveRecord model that provides data to this Grid (e.g. "User") or the model's class (e.g. User).
17
+ # Model is optional if you provide custom implementation of the endpoints.
18
+ #
19
+ # [record_id]
20
+ #
21
+ # Id of the record to be displayd in the form. Also see +:record+
22
+ #
23
+ # [record]
24
+ #
25
+ # Record to be displayd in the form. Takes precedence over +:record_id+
26
+ #
27
+ # [items]
28
+ #
29
+ # The layout of the fields as an array. See "Layout configuration".
30
+ #
31
+ # [mode]
32
+ #
33
+ # Render mode, accepted options:
34
+ #
35
+ # * +lockable+ - makes the form panel load initially in "display mode", then lets "unlock" it, change the values, and "lock" it again, while updating the values on the server
36
+ #
37
+ # == Configuring attributes
38
+ #
39
+ # === Overriding individual attributes
40
+ # Use the +attribute+ DSL method to override configuration for a specific attribute. See +Basepack::Attributes+.
41
+ #
42
+ # === Layout configuration
43
+ #
44
+ # The layout of the form is configured by supplying the +item+ config option, same way it would be configured in Ext (thus allowing for complex form layouts). Form will expand fields by looking at their names (unless +bind+ is set to +false+ for a specific field).
45
+ #
46
+ # == Endpoints
47
+ # Form implements the following endpoints:
48
+ #
49
+ # * +load+ - loads a record with a given id from the server, e.g.:
50
+ #
51
+ # someForm.server.load({id: 100});
52
+ #
53
+ # * +submit+ - gets called when the form gets submitted (e.g. by pressing the Apply button, or by calling netzkeOnApply)
54
+ # * +get_combobox_options+ - gets called when a 'remote' combobox field gets expanded
55
+ class Base < Netzke::Base
56
+ include Netzke::Form::Endpoints
57
+ include Netzke::Form::Services
58
+ include Netzke::Basepack::Attributes
59
+ include Netzke::Basepack::Fields
60
+ include Netzke::Basepack::DataAccessor
61
+
62
+ client_class do |c|
63
+ c.extend = "Ext.form.Panel"
64
+ c.require :readonly_mode
65
+ end
66
+
67
+ def configure_client(c)
68
+ super
69
+
70
+ configure_locked(c)
71
+
72
+ if model_adapter
73
+ c.pri = model_adapter.primary_key
74
+ end
75
+
76
+ if !c.multiedit
77
+ c.record = js_record_data if record
78
+ else
79
+ c.record_id = c.record = nil if c.multiedit # never set record_id in multi-edit mode
80
+ end
81
+ end
82
+
83
+ action :apply do |a|
84
+ a.icon = :tick
85
+ end
86
+
87
+ action :edit do |a|
88
+ a.icon = :pencil
89
+ end
90
+
91
+ action :cancel do |a|
92
+ a.icon = :cancel
93
+ end
94
+
95
+ def configure_locked(c)
96
+ c[:locked] = c[:locked].nil? ? (c[:mode] == :lockable) : c[:locked]
97
+ end
98
+
99
+ # Extra JavaScripts and stylesheets
100
+ client_styles do |c|
101
+ c.require :readonly_mode
102
+ end
103
+
104
+ # A hash of record data including the meta field
105
+ def js_record_data
106
+ model_adapter.record_to_hash(record, fields.values).merge(:meta => meta_field).netzke_literalize_keys
107
+ end
108
+
109
+ def record
110
+ @record ||= config[:record] || config[:record_id] && model_adapter.find_record(config[:record_id])
111
+ end
112
+
113
+ def bbar
114
+ config.has_key?(:bbar) ? config[:bbar] : default_bbar
115
+ end
116
+
117
+ def default_bbar
118
+ [].tap do |bbar|
119
+ unless config.read_only
120
+ bbar << "->" << :apply
121
+ end
122
+ end
123
+ end
124
+
125
+ def multiedit?
126
+ !!config.multiedit
127
+ end
128
+
129
+ private
130
+
131
+ def validate_config(c)
132
+ c.bbar = bbar
133
+ super
134
+ end
135
+
136
+ def normalize_config
137
+ config.items = items
138
+ @fields_from_items = {} # will be built during execution of `super`
139
+ super
140
+ end
141
+
142
+ def self.server_side_config_options
143
+ super + [:scope]
144
+ end
145
+
146
+ def meta_field
147
+ {}.tap do |res|
148
+ assoc_values = get_association_values
149
+ res[:association_values] = assoc_values.netzke_literalize_keys if record && !assoc_values.empty?
150
+ end
151
+ end
152
+
153
+ def get_association_values
154
+ fields_that_need_associated_values = fields.select{ |k,v| k.to_s.index("__") && !fields[k][:nested_attribute] }
155
+ # Take care of Ruby 1.8.7
156
+ if fields_that_need_associated_values.is_a?(Array)
157
+ fields_that_need_associated_values = fields_that_need_associated_values.inject({}){|r,(k,v)| r.merge(k => v)}
158
+ end
159
+
160
+ fields_that_need_associated_values.each_pair.inject({}) do |r,(k,v)|
161
+ r.merge(k => model_adapter.record_value_for_attribute(record, fields_that_need_associated_values[k], true))
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end