netzke-basepack 0.5.8 → 0.5.9
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.rdoc +18 -0
- data/README.rdoc +11 -4
- data/Rakefile +19 -3
- data/TODO.rdoc +1 -1
- data/generators/netzke_basepack/netzke_basepack_generator.rb +13 -0
- data/generators/netzke_basepack/templates/create_netzke_field_lists.rb +18 -0
- data/generators/netzke_basepack/templates/public_assets/ts-checkbox.gif +0 -0
- data/install.rb +1 -1
- data/javascripts/basepack.js +124 -30
- data/lib/app/models/netzke_field_list.rb +261 -0
- data/lib/app/models/netzke_model_attr_list.rb +21 -0
- data/lib/app/models/netzke_persistent_array_auto_model.rb +58 -0
- data/lib/netzke-basepack.rb +17 -2
- data/lib/netzke/active_record.rb +10 -0
- data/lib/netzke/active_record/association_attributes.rb +102 -0
- data/lib/netzke/active_record/attributes.rb +100 -0
- data/lib/netzke/active_record/combobox_options.rb +43 -0
- data/lib/netzke/active_record/data_accessor.rb +9 -12
- data/lib/netzke/attributes_configurator.rb +195 -0
- data/lib/netzke/basic_app.rb +47 -4
- data/lib/netzke/configuration_panel.rb +1 -1
- data/lib/netzke/data_accessor.rb +7 -30
- data/lib/netzke/fields_configurator.rb +106 -41
- data/lib/netzke/form_panel.rb +28 -125
- data/lib/netzke/form_panel/form_panel_api.rb +2 -3
- data/lib/netzke/form_panel/form_panel_fields.rb +147 -0
- data/lib/netzke/form_panel/form_panel_js.rb +35 -15
- data/lib/netzke/grid_panel.rb +130 -213
- data/lib/netzke/grid_panel/grid_panel_api.rb +254 -257
- data/lib/netzke/grid_panel/grid_panel_columns.rb +226 -0
- data/lib/netzke/grid_panel/grid_panel_js.rb +126 -119
- data/lib/netzke/grid_panel/record_form_window.rb +7 -1
- data/lib/netzke/json_array_editor.rb +61 -0
- data/lib/netzke/plugins/configuration_tool.rb +1 -1
- data/lib/netzke/property_editor.rb +3 -3
- data/lib/netzke/search_panel.rb +164 -27
- data/lib/netzke/tab_panel.rb +14 -12
- data/stylesheets/basepack.css +43 -2
- data/test/app_root/app/models/book.rb +1 -1
- data/test/app_root/app/models/role.rb +3 -0
- data/test/app_root/app/models/user.rb +3 -0
- data/test/app_root/config/database.yml +1 -1
- data/test/app_root/db/migrate/20090102223630_create_netzke_field_lists.rb +18 -0
- data/test/app_root/db/migrate/20090423214303_create_roles.rb +11 -0
- data/test/app_root/db/migrate/20090423222114_create_users.rb +12 -0
- data/test/fixtures/books.yml +4 -2
- data/test/fixtures/categories.yml +2 -2
- data/test/fixtures/genres.yml +6 -6
- data/test/fixtures/roles.yml +8 -0
- data/test/fixtures/users.yml +11 -0
- data/test/test_helper.rb +2 -0
- data/test/unit/active_record_basepack_test.rb +2 -2
- data/test/unit/fields_configuration_test.rb +18 -0
- data/test/unit/grid_panel_test.rb +29 -27
- metadata +41 -16
- data/lib/app/models/netzke_auto_column.rb +0 -4
- data/lib/app/models/netzke_auto_field.rb +0 -4
- data/lib/app/models/netzke_auto_table.rb +0 -61
- data/lib/netzke/active_record/basepack.rb +0 -134
- data/lib/netzke/grid_panel/javascripts/filters.js +0 -7
- data/test/app_root/db/migrate/20090102223630_create_netzke_layouts.rb +0 -14
- data/test/unit/helper_model_test.rb +0 -30
@@ -0,0 +1,226 @@
|
|
1
|
+
module Netzke
|
2
|
+
class GridPanel < Base
|
3
|
+
module GridPanelColumns
|
4
|
+
module ClassMethods
|
5
|
+
# Columns to be displayed by the FieldConfigurator, "meta-columns". Each corresponds to a configuration
|
6
|
+
# option for each column in the grid.
|
7
|
+
def meta_columns
|
8
|
+
[
|
9
|
+
# Whether the column will be present in the grid, also in :hidden or :meta state. The value for this column will
|
10
|
+
# always be sent to/from the JS grid to the server
|
11
|
+
{:name => "included", :attr_type => :boolean, :width => 40, :header => "Incl", :default_value => true},
|
12
|
+
|
13
|
+
# The name of the column. May be any accessible method or attribute of the data_class.
|
14
|
+
{:name => "name", :attr_type => :string, :width => 200},
|
15
|
+
|
16
|
+
# The header for the column.
|
17
|
+
{:name => "label", :attr_type => :string, :width => 200, :header => "Header"},
|
18
|
+
|
19
|
+
# The default value of this column. Is used when a new row in the grid gets created.
|
20
|
+
{:name => "default_value", :attr_type => :string, :width => 200},
|
21
|
+
|
22
|
+
# Options for drop-downs
|
23
|
+
{:name => "combobox_options", :attr_type => :string, :editor => "textarea", :width => 200},
|
24
|
+
|
25
|
+
# Whether the column is editable in the grid.
|
26
|
+
{:name => "read_only", :attr_type => :boolean, :header => "R/O", :tooltip => "Read-only"},
|
27
|
+
|
28
|
+
# Whether the column will be in the hidden state (hide/show columns from the column menu, if it's enabled).
|
29
|
+
{:name => "hidden", :attr_type => :boolean},
|
30
|
+
|
31
|
+
# Whether the column should have "grid filters" enabled
|
32
|
+
# (see here: http://www.extjs.com/deploy/dev/examples/grid-filtering/grid-filter-local.html)
|
33
|
+
{:name => "with_filters", :attr_type => :boolean, :default_value => true, :header => "Filters"},
|
34
|
+
|
35
|
+
#
|
36
|
+
# Below some rarely used parameters, hidden by default (you can always un-hide them from the column menu).
|
37
|
+
#
|
38
|
+
|
39
|
+
# The column's width
|
40
|
+
{:name => "width", :attr_type => :integer, :hidden => true},
|
41
|
+
|
42
|
+
# Whether the column should be hideable
|
43
|
+
{:name => "hideable", :attr_type => :boolean, :default_value => true, :hidden => true},
|
44
|
+
|
45
|
+
# Whether the column should be sortable (why change it? normally it's hardcoded)
|
46
|
+
{:name => "sortable", :attr_type => :boolean, :default_value => true, :hidden => true},
|
47
|
+
|
48
|
+
#
|
49
|
+
# And finally some meta columns that we probably never want to see in the GUI
|
50
|
+
#
|
51
|
+
{:name => "editor", :attr_type => :string, :meta => true}
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
module InstanceMethods
|
58
|
+
|
59
|
+
# Normalized columns for the grid, e.g.:
|
60
|
+
# [{:name => :id, :hidden => true, ...}, {:name => :name, :editable => false, ...}, ...]
|
61
|
+
def columns(only_included = true)
|
62
|
+
@columns ||= begin
|
63
|
+
if cols = load_columns
|
64
|
+
filter_out_excluded_columns(cols) if only_included
|
65
|
+
cols
|
66
|
+
else
|
67
|
+
initial_columns(only_included)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Columns that we fall back to when neither persistent columns, nor configured columns are present.
|
73
|
+
# If there's a model-level field configuration, it's being used.
|
74
|
+
# Otherwise the defaults straight from the ActiveRecord model ("netzke_attributes").
|
75
|
+
# Override this method if you want to provide a fix set of columns in your subclass.
|
76
|
+
def default_columns
|
77
|
+
@default_columns ||= load_model_level_attrs || data_class.netzke_attributes
|
78
|
+
# @default_columns ||= load_model_level_attrs || data_class.netzke_attributes
|
79
|
+
end
|
80
|
+
|
81
|
+
# Columns that represent a smart merge of default_columns and columns passed during the configuration.
|
82
|
+
def initial_columns(only_included = true)
|
83
|
+
# Normalize here, as from the config we can get symbols (names) instead of hashes
|
84
|
+
columns_from_config = config[:columns] && normalize_attr_config(config[:columns])
|
85
|
+
|
86
|
+
if columns_from_config
|
87
|
+
# reverse-merge each column hash from config with each column hash from exposed_attributes (columns from config have higher priority)
|
88
|
+
for c in columns_from_config
|
89
|
+
corresponding_default_column = default_columns.find{ |k| k[:name] == c[:name] }
|
90
|
+
c.reverse_merge!(corresponding_default_column) if corresponding_default_column
|
91
|
+
end
|
92
|
+
columns_for_create = columns_from_config
|
93
|
+
else
|
94
|
+
# we didn't have columns configured in widget's config, so, use the columns from the data class
|
95
|
+
columns_for_create = default_columns
|
96
|
+
end
|
97
|
+
|
98
|
+
filter_out_excluded_columns(columns_for_create) if only_included
|
99
|
+
|
100
|
+
# Make the column config complete with the defaults
|
101
|
+
columns_for_create.each do |c|
|
102
|
+
detect_association(c)
|
103
|
+
set_default_header(c)
|
104
|
+
set_default_editor(c)
|
105
|
+
set_default_width(c)
|
106
|
+
set_default_hidden(c)
|
107
|
+
set_default_editable(c)
|
108
|
+
set_default_sortable(c)
|
109
|
+
set_default_filterable(c)
|
110
|
+
end
|
111
|
+
|
112
|
+
columns_for_create
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
def filter_out_excluded_columns(cols)
|
119
|
+
cols.reject!{ |c| c[:included] == false }
|
120
|
+
end
|
121
|
+
|
122
|
+
# Stores modified columns in persistent storage
|
123
|
+
def save_columns!
|
124
|
+
NetzkeFieldList.update_list_for_current_authority(global_id, columns(false), data_class.name)
|
125
|
+
end
|
126
|
+
|
127
|
+
def load_columns
|
128
|
+
NetzkeFieldList.read_list(global_id) if persistent_config_enabled?
|
129
|
+
end
|
130
|
+
|
131
|
+
def load_model_level_attrs
|
132
|
+
NetzkeModelAttrList.read_list(data_class.name)
|
133
|
+
end
|
134
|
+
|
135
|
+
# whether a column is bound to the primary_key
|
136
|
+
def reflects_primary_key?(c)
|
137
|
+
c[:name] == data_class.primary_key
|
138
|
+
end
|
139
|
+
|
140
|
+
def set_default_header(c)
|
141
|
+
c[:label] ||= c[:name].humanize
|
142
|
+
end
|
143
|
+
|
144
|
+
def set_default_editor(c)
|
145
|
+
c[:editor] ||= editor_for_attr_type(c[:attr_type])
|
146
|
+
end
|
147
|
+
|
148
|
+
def set_default_width(c)
|
149
|
+
c[:width] ||= 50 if c[:attr_type] == :boolean
|
150
|
+
c[:width] ||= 150 if c[:attr_type] == :datetime
|
151
|
+
end
|
152
|
+
|
153
|
+
def set_default_hidden(c)
|
154
|
+
c[:hidden] = true if reflects_primary_key?(c) && c[:hidden].nil?
|
155
|
+
end
|
156
|
+
|
157
|
+
def set_default_editable(c)
|
158
|
+
c[:editable] = c[:read_only].nil? ? !(reflects_primary_key?(c) || c[:virtual]) : !c[:read_only]
|
159
|
+
c.delete(:read_only)
|
160
|
+
end
|
161
|
+
|
162
|
+
def set_default_sortable(c)
|
163
|
+
c[:sortable] = !c[:virtual]
|
164
|
+
end
|
165
|
+
|
166
|
+
def set_default_filterable(c)
|
167
|
+
c[:filterable] = !c[:virtual]
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns editor's xtype for a column type
|
171
|
+
def editor_for_attr_type(type)
|
172
|
+
attr_type_to_editor_map[type]
|
173
|
+
end
|
174
|
+
|
175
|
+
def editor_for_association
|
176
|
+
:combobox
|
177
|
+
end
|
178
|
+
|
179
|
+
# Returns a hash that maps a column type to the editor xtype. Override if you want different editors.
|
180
|
+
def attr_type_to_editor_map
|
181
|
+
{
|
182
|
+
:integer => :numberfield,
|
183
|
+
:boolean => :checkbox,
|
184
|
+
:date => :datefield,
|
185
|
+
:datetime => :xdatetime,
|
186
|
+
:text => :textarea,
|
187
|
+
:string => :textfield
|
188
|
+
}
|
189
|
+
end
|
190
|
+
|
191
|
+
# Detects an association column and sets up the proper editor.
|
192
|
+
# If a column is a foreign key (e.g. "category_id"), also renames the column into "normalized" association column, e.g.:
|
193
|
+
# category__name
|
194
|
+
# If association doesn't respond to methods "name", "title" or "label", falls back to "id", e.g.:
|
195
|
+
# category__id
|
196
|
+
def detect_association(c)
|
197
|
+
# named as foreign key of some association?
|
198
|
+
assoc = data_class.reflect_on_all_associations.detect{|a| a.primary_key_name == c[:name]}
|
199
|
+
|
200
|
+
if assoc && !assoc.options[:polymorphic]
|
201
|
+
assoc_method = %w{name title label id}.detect{|m| (assoc.klass.instance_methods + assoc.klass.column_names).include?(m) } || assoc.klass.primary_key
|
202
|
+
c[:name] = "#{assoc.name}__#{assoc_method}"
|
203
|
+
end
|
204
|
+
|
205
|
+
# named with an double-underscore notation? surely an association column then
|
206
|
+
if !assoc && c[:name].index('__')
|
207
|
+
assoc_name, assoc_method = c[:name].split('__')
|
208
|
+
assoc = data_class.reflect_on_association(assoc_name.to_sym)
|
209
|
+
end
|
210
|
+
|
211
|
+
if assoc && assoc_method
|
212
|
+
assoc_column = assoc.klass.columns_hash[assoc_method]
|
213
|
+
assoc_method_type = assoc_column.try(:type)
|
214
|
+
|
215
|
+
# if association column is boolean, display a checkbox (or alike), otherwise - a combobox (or alike)
|
216
|
+
c[:editor] = assoc_method_type == :boolean ? editor_for_attr_type(:boolean) : editor_for_association
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.included(receiver)
|
221
|
+
receiver.extend ClassMethods
|
222
|
+
receiver.send :include, InstanceMethods
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
@@ -1,26 +1,27 @@
|
|
1
1
|
module Netzke
|
2
2
|
class GridPanel < Base
|
3
|
+
# (Dynamic) JavaScript for GridPanel
|
3
4
|
module GridPanelJs
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
# The result of this method (a hash) is converted to a JSON object and passed as the configuration parameter
|
7
|
+
# to the constructor of our JavaScript class. Override it when you want to pass any extra configuration
|
8
|
+
# to the JavaScript side.
|
8
9
|
def js_config
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
super.merge(
|
11
|
+
:clmns => columns, # columns
|
12
|
+
:model => config[:model], # the model name
|
13
|
+
:inline_data => (get_data if ext_config[:load_inline_data]), # inline data (loaded along with the grid panel)
|
14
|
+
:pri => data_class.primary_key # table primary key name
|
15
|
+
)
|
15
16
|
end
|
16
17
|
|
17
18
|
module ClassMethods
|
18
|
-
|
19
|
+
|
19
20
|
def js_base_class
|
20
21
|
'Ext.grid.EditorGridPanel'
|
21
22
|
end
|
22
23
|
|
23
|
-
# Ext.Component#initComponent, built up from pices (dependent on class configuration)
|
24
|
+
# Ext.Component#initComponent, built up from pices (dependent on class-level configuration)
|
24
25
|
def js_init_component
|
25
26
|
|
26
27
|
# Optional "edit in form"-related events
|
@@ -45,13 +46,11 @@ module Netzke
|
|
45
46
|
// Normalize columns passed in the config
|
46
47
|
var normClmns = [];
|
47
48
|
Ext.each(this.clmns, function(c){
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
normClmns.push(c);
|
54
|
-
}
|
49
|
+
// normalize columns
|
50
|
+
if (typeof c == 'string') {
|
51
|
+
normClmns.push({name:c});
|
52
|
+
} else {
|
53
|
+
normClmns.push(c);
|
55
54
|
}
|
56
55
|
});
|
57
56
|
|
@@ -61,9 +60,12 @@ module Netzke
|
|
61
60
|
this.plugins = []; // checkbox colums is a special case, being a plugin
|
62
61
|
|
63
62
|
var filters = [];
|
64
|
-
|
65
|
-
// Run through columns
|
63
|
+
|
64
|
+
// Run through columns and set up different configuration for each
|
66
65
|
Ext.each(normClmns, function(c){
|
66
|
+
// We will not use meta columns as actual columns (not even hidden) - only to create the records
|
67
|
+
if (c.meta) return;
|
68
|
+
|
67
69
|
// Apply default column config
|
68
70
|
Ext.applyIf(c, this.defaultColumnConfig);
|
69
71
|
|
@@ -71,20 +73,24 @@ module Netzke
|
|
71
73
|
c.dataIndex = c.name;
|
72
74
|
|
73
75
|
// Automatically calculated default values
|
74
|
-
if (!c.header) {c.header = c.name.humanize()}
|
76
|
+
if (!c.header) {c.header = c.label || c.name.humanize()}
|
75
77
|
|
76
78
|
// normalize editor
|
77
79
|
if (c.editor) {
|
78
80
|
c.editor = Netzke.isObject(c.editor) ? c.editor : {xtype:c.editor};
|
79
81
|
} else {
|
80
|
-
c.editor = {xtype: 'textfield'}
|
82
|
+
c.editor = {xtype: this.attrTypeEditorMap[c.attrType] || 'textfield'}
|
81
83
|
}
|
82
|
-
|
84
|
+
|
85
|
+
// if comboboxOptions are provided, we render a combobox instead of textfield
|
86
|
+
if (c.comboboxOptions && c.editor.xtype === "textfield") {
|
87
|
+
c.editor = {xtype: "combobox", options: c.comboboxOptions.split('\\n')}
|
88
|
+
}
|
89
|
+
|
83
90
|
// collect filters
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
//}
|
91
|
+
if (c.filterable){
|
92
|
+
filters.push({type:this.filterTypeForAttrType(c.attrType), dataIndex:c.name});
|
93
|
+
}
|
88
94
|
|
89
95
|
if (c.editor && c.editor.xtype == 'checkbox') {
|
90
96
|
// Special case of checkbox column
|
@@ -109,12 +115,17 @@ module Netzke
|
|
109
115
|
if (c.renderer && !Ext.isArray(c.renderer) && c.renderer.match(/^\\s*function\\s*\\(/)) {
|
110
116
|
// if the renderer is an inline function - eval it (double escaping because we are inside of the Ruby string here...)
|
111
117
|
eval("c.renderer = " + c.renderer + ";");
|
118
|
+
} else if (Ext.isFunction(this[c.renderer])) {
|
119
|
+
// whether the renderer is defined in this.scope
|
120
|
+
c.renderer = this[c.renderer].createDelegate(this);
|
112
121
|
} else {
|
113
122
|
// othrewise it's a string representing the name of the renderer or an json-encoded array,
|
114
123
|
// where the first parameter is the renderer's name, and the rest - parameters that should be
|
115
124
|
// passed to the renderer at the moment of calling
|
116
125
|
var renderer = Ext.netzke.normalizedRenderer(c.renderer);
|
117
|
-
if (renderer != null)
|
126
|
+
if (renderer != null) {
|
127
|
+
c.renderer = renderer
|
128
|
+
};
|
118
129
|
}
|
119
130
|
|
120
131
|
// add to the list
|
@@ -132,14 +143,13 @@ module Netzke
|
|
132
143
|
/* ... and done with columns */
|
133
144
|
|
134
145
|
// Filters
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
// }
|
146
|
+
if (this.enableColumnFilters) {
|
147
|
+
this.plugins.push(new Ext.ux.grid.GridFilters({filters:filters}));
|
148
|
+
}
|
139
149
|
|
140
150
|
// Create Ext.data.Record constructor specific for our particular column configuration
|
141
151
|
this.recordConfig = [];
|
142
|
-
Ext.each(normClmns, function(column){this.recordConfig.push({name:column.name});}, this);
|
152
|
+
Ext.each(normClmns, function(column){this.recordConfig.push({name:column.name, defaultValue:column.defaultValue});}, this);
|
143
153
|
this.Row = Ext.data.Record.create(this.recordConfig);
|
144
154
|
|
145
155
|
// Drag'n'Drop
|
@@ -200,8 +210,9 @@ module Netzke
|
|
200
210
|
this.bbar = (this.enablePagination) ? new Ext.PagingToolbar({
|
201
211
|
pageSize : this.rowsPerPage,
|
202
212
|
items : this.bbar ? ["-"].concat(this.bbar) : [],
|
203
|
-
store : this.store,
|
204
|
-
emptyMsg: 'Empty'
|
213
|
+
store : this.store,
|
214
|
+
emptyMsg: 'Empty',
|
215
|
+
displayInfo: true
|
205
216
|
}) : this.bbar;
|
206
217
|
|
207
218
|
// Selection model
|
@@ -260,31 +271,60 @@ module Netzke
|
|
260
271
|
|
261
272
|
end
|
262
273
|
|
274
|
+
# All the rest that makes our JavaScript class
|
263
275
|
def js_extend_properties
|
264
276
|
res = super
|
265
277
|
|
266
|
-
# Generic (non-optional) functionality
|
267
278
|
res.merge!(
|
268
279
|
{
|
280
|
+
# all the options are overrideable in config, of course
|
269
281
|
:track_mouse_over => true,
|
270
282
|
:load_mask => true,
|
271
283
|
:auto_scroll => true,
|
272
284
|
|
273
|
-
:default_column_config =>
|
285
|
+
:default_column_config => meta_columns.inject({}){ |r, c| c.is_a?(Hash) ? r.merge(c[:name] => c[:default]) : r },
|
274
286
|
|
275
287
|
:init_component => js_init_component.l,
|
276
288
|
|
289
|
+
:attr_type_editor_map => {
|
290
|
+
:integer => "numberfield",
|
291
|
+
:boolean => "checkbox",
|
292
|
+
:decimal => "numberfield",
|
293
|
+
:datetime => "xdatetime",
|
294
|
+
:date => "datefield",
|
295
|
+
:string => "textfield"
|
296
|
+
},
|
297
|
+
|
298
|
+
:filter_type_for_attr_type => <<-END_OF_JAVASCRIPT.l,
|
299
|
+
function(attrType){
|
300
|
+
var map = {
|
301
|
+
integer :'Numeric',
|
302
|
+
decimal :'Numeric',
|
303
|
+
datetime:'Date',
|
304
|
+
date :'Date',
|
305
|
+
string :'String',
|
306
|
+
};
|
307
|
+
map['boolean'] = "Boolean"; // "boolean" is a JS reserved word
|
308
|
+
return map[attrType] || 'String';
|
309
|
+
}
|
310
|
+
END_OF_JAVASCRIPT
|
311
|
+
|
277
312
|
# Handlers for actions
|
278
313
|
#
|
279
314
|
|
280
315
|
:on_add => <<-END_OF_JAVASCRIPT.l,
|
281
316
|
function(){
|
282
|
-
var
|
283
|
-
var r = new this.Row(rowConfig); // TODO: add default values
|
317
|
+
var r = new this.Row();
|
284
318
|
r.isNew = true; // to distinguish new records
|
285
319
|
// r.set('id', r.id); // otherwise later r.get('id') returns empty string
|
286
320
|
this.stopEditing();
|
287
321
|
this.getStore().add(r);
|
322
|
+
|
323
|
+
// Set default values
|
324
|
+
this.getStore().fields.each(function(field){
|
325
|
+
r.set(field.name, field.defaultValue);
|
326
|
+
});
|
327
|
+
|
288
328
|
this.tryStartEditing(this.store.indexOf(r));
|
289
329
|
}
|
290
330
|
END_OF_JAVASCRIPT
|
@@ -466,11 +506,13 @@ module Netzke
|
|
466
506
|
function(row){
|
467
507
|
var editableIndex = 0;
|
468
508
|
Ext.each(this.getColumnModel().config, function(c){
|
469
|
-
|
509
|
+
// skip columns that cannot be edited
|
510
|
+
if (!(c.hidden == true || c.editable == false || !c.editor || c.attrType == 'boolean')) {
|
470
511
|
return false;
|
471
512
|
}
|
472
513
|
editableIndex++;
|
473
514
|
});
|
515
|
+
|
474
516
|
if (editableIndex < this.getColumnModel().config.length) {this.startEditing(row, editableIndex);}
|
475
517
|
}
|
476
518
|
END_OF_JAVASCRIPT
|
@@ -575,84 +617,44 @@ module Netzke
|
|
575
617
|
# Optional edit in form functionality
|
576
618
|
res.merge!(
|
577
619
|
{
|
578
|
-
:on_successfull_record_creation => <<-END_OF_JAVASCRIPT.l,
|
579
|
-
function(){
|
580
|
-
this.formWindow.hide();
|
581
|
-
this.getStore().reload();
|
582
|
-
}
|
583
|
-
END_OF_JAVASCRIPT
|
584
|
-
|
585
|
-
:on_successfull_edit => <<-END_OF_JAVASCRIPT.l,
|
586
|
-
function(){
|
587
|
-
this.editFormWindow.close();
|
588
|
-
delete this.editFormWindow;
|
589
|
-
this.getStore().reload();
|
590
|
-
}
|
591
|
-
END_OF_JAVASCRIPT
|
592
|
-
|
593
620
|
:on_edit_in_form => <<-END_OF_JAVASCRIPT.l,
|
594
621
|
function(){
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
aggr.on('apply', function(){
|
629
|
-
var ids = [];
|
630
|
-
selModel.each(function(r){
|
631
|
-
ids.push(r.id);
|
632
|
-
});
|
633
|
-
aggr.baseParams = {ids: Ext.encode(ids)}
|
634
|
-
}, this);
|
635
|
-
},
|
636
|
-
scope: this
|
637
|
-
});
|
638
|
-
} else {
|
639
|
-
|
640
|
-
// single edit
|
641
|
-
this.editFormWindow.setTitle('Edit');
|
642
|
-
var recordId = selModel.getSelected().id;
|
643
|
-
this.loadAggregatee({
|
644
|
-
id: "editForm",
|
645
|
-
container: this.editFormWindow.id,
|
646
|
-
params: {
|
647
|
-
record_id: recordId
|
648
|
-
}
|
649
|
-
});
|
650
|
-
}
|
651
|
-
}, this);
|
652
|
-
|
622
|
+
var selModel = this.getSelectionModel();
|
623
|
+
if (selModel.getCount() > 1) {
|
624
|
+
var recordId = selModel.getSelected().id;
|
625
|
+
this.loadAggregatee({id: "multiEditForm",
|
626
|
+
params: {record_id: recordId},
|
627
|
+
callback: function(w){
|
628
|
+
var form = w.items.first();
|
629
|
+
form.on('apply', function(){
|
630
|
+
var ids = [];
|
631
|
+
selModel.each(function(r){
|
632
|
+
ids.push(r.id);
|
633
|
+
});
|
634
|
+
form.baseParams = {ids: Ext.encode(ids)}
|
635
|
+
}, this);
|
636
|
+
|
637
|
+
w.on('close', function(){
|
638
|
+
if (w.closeRes === "ok") {
|
639
|
+
this.store.reload();
|
640
|
+
}
|
641
|
+
}, this);
|
642
|
+
}, scope: this});
|
643
|
+
} else {
|
644
|
+
var recordId = selModel.getSelected().id;
|
645
|
+
this.loadAggregatee({id: "editForm",
|
646
|
+
params: {record_id: recordId},
|
647
|
+
callback: function(form){
|
648
|
+
form.on('close', function(){
|
649
|
+
if (form.closeRes === "ok") {
|
650
|
+
this.store.reload();
|
651
|
+
}
|
652
|
+
}, this);
|
653
|
+
}, scope: this});
|
654
|
+
}
|
653
655
|
}
|
654
656
|
END_OF_JAVASCRIPT
|
655
|
-
|
657
|
+
|
656
658
|
:on_add_in_form => <<-END_OF_JAVASCRIPT.l,
|
657
659
|
function(){
|
658
660
|
this.loadAggregatee({id: "addForm", callback: function(form){
|
@@ -679,7 +681,7 @@ module Netzke
|
|
679
681
|
modal: true,
|
680
682
|
width: 400,
|
681
683
|
height: Ext.lib.Dom.getViewHeight() *0.9,
|
682
|
-
closeAction:'
|
684
|
+
closeAction:'close',
|
683
685
|
buttons:[{
|
684
686
|
text: 'OK',
|
685
687
|
handler: function(){
|
@@ -694,15 +696,15 @@ module Netzke
|
|
694
696
|
closePositively : function(){
|
695
697
|
this.conditions = this.getWidget().getForm().getValues();
|
696
698
|
this.closeRes = 'OK';
|
697
|
-
this.
|
699
|
+
this.close();
|
698
700
|
},
|
699
701
|
closeNegatively: function(){
|
700
702
|
this.closeRes = 'cancel';
|
701
|
-
this.
|
703
|
+
this.close();
|
702
704
|
}
|
703
705
|
});
|
704
706
|
|
705
|
-
this.searchWindow.on('
|
707
|
+
this.searchWindow.on('close', function(){
|
706
708
|
if (this.searchWindow.closeRes == 'OK'){
|
707
709
|
var searchConditions = this.searchWindow.conditions;
|
708
710
|
var filtered = false;
|
@@ -742,6 +744,11 @@ module Netzke
|
|
742
744
|
res
|
743
745
|
end
|
744
746
|
end
|
747
|
+
|
748
|
+
def self.included(base)
|
749
|
+
base.extend ClassMethods
|
750
|
+
end
|
751
|
+
|
745
752
|
end
|
746
753
|
end
|
747
754
|
end
|