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
@@ -29,7 +29,6 @@ module Netzke
|
|
29
29
|
begin
|
30
30
|
@record.send("#{k}=",v)
|
31
31
|
rescue StandardError => exc
|
32
|
-
logger.debug "!!! FormPanelApi#create_or_update_record exception: #{exc.inspect}\n"
|
33
32
|
flash :error => exc.message
|
34
33
|
success = false
|
35
34
|
break
|
@@ -66,12 +65,12 @@ module Netzke
|
|
66
65
|
|
67
66
|
def configuration_panel__fields__get_combobox_options(params)
|
68
67
|
query = params[:query]
|
69
|
-
{:data => (
|
68
|
+
{:data => (default_columns.map{ |c| c[:name].to_s }).grep(/^#{query}/).map{ |n| [n] }}.to_nifty_json
|
70
69
|
end
|
71
70
|
|
72
71
|
# Returns array of form values according to the configured columns
|
73
72
|
def array_of_values
|
74
|
-
@record && @record.to_array(
|
73
|
+
@record && @record.to_array(fields, self)
|
75
74
|
end
|
76
75
|
end
|
77
76
|
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Netzke
|
2
|
+
class FormPanel < Base
|
3
|
+
module FormPanelFields
|
4
|
+
module ClassMethods
|
5
|
+
# Columns to be displayed by the FieldConfigurator, "meta-columns". Each corresponds to a configuration
|
6
|
+
# option for each field in the form.
|
7
|
+
def meta_columns
|
8
|
+
[
|
9
|
+
{:name => "included", :attr_type => :boolean, :width => 40, :header => "Incl", :default_value => true},
|
10
|
+
{:name => "name", :attr_type => :string, :editor => :combobox, :width => 200},
|
11
|
+
{:name => "label", :attr_type => :string, :header => "Label"},
|
12
|
+
{:name => "default_value", :attr_type => :string}
|
13
|
+
]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
def fields
|
19
|
+
@fields ||= begin
|
20
|
+
flds = load_fields
|
21
|
+
flds ||= initial_fields
|
22
|
+
|
23
|
+
flds.map! do |c|
|
24
|
+
value = record.send(c[:name])
|
25
|
+
value.nil? ? c : c.merge(:value => value)
|
26
|
+
end if record
|
27
|
+
|
28
|
+
flds
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def default_fields
|
33
|
+
@default_fields ||= load_model_level_attrs || (data_class && data_class.netzke_attributes) || []
|
34
|
+
end
|
35
|
+
|
36
|
+
def initial_fields(only_included = true)
|
37
|
+
::ActiveSupport::Deprecation.warn("The :columns option for FormPanel is deprecated. Use :fields instead", caller) if config[:columns]
|
38
|
+
|
39
|
+
# Normalize here, as from the config we can get symbols (names) instead of hashes
|
40
|
+
fields_from_config = (config[:columns] || config[:fields]) && normalize_attr_config(config[:columns] || config[:fields])
|
41
|
+
|
42
|
+
if fields_from_config
|
43
|
+
# reverse-merge each column hash from config with each column hash from exposed_attributes (fields from config have higher priority)
|
44
|
+
for c in fields_from_config
|
45
|
+
corresponding_exposed_column = default_fields.find{ |k| k[:name] == c[:name] }
|
46
|
+
c.reverse_merge!(corresponding_exposed_column) if corresponding_exposed_column
|
47
|
+
end
|
48
|
+
fields_for_create = fields_from_config
|
49
|
+
elsif default_fields
|
50
|
+
# we didn't have fields configured in widget's config, so, use the fields from the data class
|
51
|
+
fields_for_create = default_fields
|
52
|
+
else
|
53
|
+
raise ArgumentError, "No fields specified for widget '#{global_id}'"
|
54
|
+
end
|
55
|
+
|
56
|
+
fields_for_create.reject!{ |c| c[:included] == false }
|
57
|
+
|
58
|
+
fields_for_create.map! do |c|
|
59
|
+
if data_class
|
60
|
+
|
61
|
+
detect_association_with_method(c)
|
62
|
+
|
63
|
+
# detect association column (e.g. :category_id)
|
64
|
+
if assoc = data_class.reflect_on_all_associations.detect{|a| a.primary_key_name == c[:name]}
|
65
|
+
c[:xtype] ||= xtype_for_association
|
66
|
+
assoc_method = %w{name title label id}.detect{|m| (assoc.klass.instance_methods + assoc.klass.column_names).include?(m) } || assoc.klass.primary_key
|
67
|
+
c[:name] = "#{assoc.name}__#{assoc_method}"
|
68
|
+
end
|
69
|
+
|
70
|
+
c[:hidden] = true if c[:name] == data_class.primary_key && c[:hidden].nil? # hide ID column by default
|
71
|
+
end
|
72
|
+
|
73
|
+
set_default_field_label(c)
|
74
|
+
|
75
|
+
c[:xtype] ||= xtype_for_attr_type(c[:attr_type]) # unless xtype_map[type].nil?
|
76
|
+
c
|
77
|
+
end
|
78
|
+
|
79
|
+
fields_for_create
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
# Stores modified fields in persistent storage (not used in forms, as we can't modify them on the fly, only via FieldsConfigurator)
|
86
|
+
# def save_fields!
|
87
|
+
# NetzkeFieldList.update_list_for_current_authority(global_id, fields, data_class.name)
|
88
|
+
# end
|
89
|
+
|
90
|
+
def load_fields
|
91
|
+
NetzkeFieldList.read_list(global_id) if persistent_config_enabled?
|
92
|
+
end
|
93
|
+
|
94
|
+
def load_model_level_attrs
|
95
|
+
NetzkeModelAttrList.read_list(data_class.name) if data_class
|
96
|
+
end
|
97
|
+
|
98
|
+
def set_default_field_label(c)
|
99
|
+
c[:label] ||= c[:name].humanize
|
100
|
+
end
|
101
|
+
|
102
|
+
def attr_type_to_xtype_map
|
103
|
+
{
|
104
|
+
:integer => :numberfield,
|
105
|
+
:boolean => :xcheckbox,
|
106
|
+
:date => :datefield,
|
107
|
+
:datetime => :xdatetime,
|
108
|
+
:text => :textarea,
|
109
|
+
:json => :jsonfield
|
110
|
+
# :string => :textfield
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def xtype_for_attr_type(type)
|
115
|
+
attr_type_to_xtype_map[type]
|
116
|
+
end
|
117
|
+
|
118
|
+
def xtype_for_association
|
119
|
+
:combobox
|
120
|
+
end
|
121
|
+
|
122
|
+
def detect_association_with_method(c)
|
123
|
+
if c[:name].to_s.index('__')
|
124
|
+
assoc_name, method = c[:name].split('__').map(&:to_sym)
|
125
|
+
if assoc = data_class.reflect_on_association(assoc_name)
|
126
|
+
assoc_column = assoc.klass.columns_hash[method.to_s]
|
127
|
+
assoc_method_type = assoc_column.try(:type)
|
128
|
+
if assoc_method_type
|
129
|
+
c[:xtype] ||= assoc_method_type == :boolean ? xtype_for_attr_type(assoc_method_type) : :combobox
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
def self.included(receiver)
|
138
|
+
receiver.extend ClassMethods
|
139
|
+
receiver.send :include, InstanceMethods
|
140
|
+
|
141
|
+
receiver.class_eval do
|
142
|
+
alias :initial_columns :initial_fields
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -1,8 +1,13 @@
|
|
1
1
|
module Netzke
|
2
2
|
class FormPanel < Base
|
3
3
|
module FormPanelJs
|
4
|
-
|
5
|
-
|
4
|
+
# parameters used to instantiate the JS object
|
5
|
+
def js_config
|
6
|
+
res = super
|
7
|
+
res.merge!(:fields => fields)
|
8
|
+
res.merge!(:model => data_class.name) if data_class
|
9
|
+
res.merge!(:pri => data_class.primary_key) if data_class
|
10
|
+
res
|
6
11
|
end
|
7
12
|
|
8
13
|
module ClassMethods
|
@@ -24,21 +29,22 @@ module Netzke
|
|
24
29
|
var index = 0;
|
25
30
|
|
26
31
|
// Process columns
|
27
|
-
Ext.each(this.
|
28
|
-
if (typeof field == 'string') field = {name:field}; // normalize field
|
32
|
+
Ext.each(this.fields, function(field){
|
29
33
|
if (!field.hidden || field.name == this.pri) {
|
30
34
|
recordFields.push({name:field.name, mapping:index++});
|
31
|
-
|
35
|
+
|
32
36
|
var defaultColumnConfig = Ext.apply({}, this.defaultColumnConfig);
|
33
37
|
var columnConfig = Ext.apply(defaultColumnConfig, field);
|
34
38
|
|
35
39
|
// apply dynamically defined properties
|
36
|
-
Ext.
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
Ext.applyIf(columnConfig, {
|
41
|
+
xtype : this.attrTypeEditorMap[columnConfig.attrType],
|
42
|
+
fieldLabel: columnConfig.fieldLabel || columnConfig.label || columnConfig.name.humanize(),
|
43
|
+
hideLabel : columnConfig.hidden, // completely hide fields marked "hidden"
|
44
|
+
parentId : this.id,
|
45
|
+
name : columnConfig.name,
|
46
|
+
value : columnConfig.value || columnConfig.defaultValue,
|
47
|
+
checked : columnConfig.attrType == "boolean" ? columnConfig.value : null // checkbox state
|
42
48
|
});
|
43
49
|
|
44
50
|
this.items.push(columnConfig);
|
@@ -48,7 +54,7 @@ module Netzke
|
|
48
54
|
var Record = Ext.data.Record.create(recordFields);
|
49
55
|
this.reader = new Ext.data.RecordArrayReader({root:"data"}, Record);
|
50
56
|
|
51
|
-
delete this.
|
57
|
+
delete this.fields; // we don't need them anymore
|
52
58
|
|
53
59
|
// Now let Ext.form.FormPanel do the rest
|
54
60
|
#{js_full_class_name}.superclass.initComponent.call(this);
|
@@ -58,6 +64,15 @@ module Netzke
|
|
58
64
|
}
|
59
65
|
END_OF_JAVASCRIPT
|
60
66
|
|
67
|
+
:attr_type_editor_map => {
|
68
|
+
:integer => "numberfield",
|
69
|
+
:boolean => "checkbox",
|
70
|
+
:decimal => "numberfield",
|
71
|
+
:datetime => "xdatetime",
|
72
|
+
:date => "datefield",
|
73
|
+
:string => "textfield"
|
74
|
+
},
|
75
|
+
|
61
76
|
# Defaults for each field
|
62
77
|
:defaults => {
|
63
78
|
:anchor => '-20', # to leave some space for the scrollbar
|
@@ -74,9 +89,9 @@ module Netzke
|
|
74
89
|
}
|
75
90
|
},
|
76
91
|
|
77
|
-
:default_column_config =>
|
78
|
-
|
79
|
-
})
|
92
|
+
# :default_column_config => meta_columns.inject({}){ |r, c| r.merge!({
|
93
|
+
# c[:name] => c[:default_value]
|
94
|
+
# })},
|
80
95
|
|
81
96
|
:set_form_values => <<-END_OF_JAVASCRIPT.l,
|
82
97
|
function(values){
|
@@ -138,6 +153,11 @@ module Netzke
|
|
138
153
|
end
|
139
154
|
|
140
155
|
end
|
156
|
+
|
157
|
+
def self.included(base)
|
158
|
+
base.extend ClassMethods
|
159
|
+
end
|
160
|
+
|
141
161
|
end
|
142
162
|
end
|
143
163
|
end
|
data/lib/netzke/grid_panel.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "netzke/grid_panel/grid_panel_js"
|
2
2
|
require "netzke/grid_panel/grid_panel_api"
|
3
|
+
require "netzke/grid_panel/grid_panel_columns"
|
3
4
|
require "netzke/plugins/configuration_tool"
|
4
5
|
require "netzke/data_accessor"
|
5
6
|
|
@@ -58,13 +59,45 @@ module Netzke
|
|
58
59
|
# * <tt>:mode</tt> - when set to <tt>:config</tt>, GridPanel loads in configuration mode
|
59
60
|
#
|
60
61
|
# Additionally supports Netzke::Base config options.
|
62
|
+
#
|
63
|
+
# == Column
|
64
|
+
# Here's how the GridPanel decides which columns in which sequence and with which configuration to display.
|
65
|
+
# First, the column configs are aquired from this GridPanel's persistent storage, as an array of hashes, each
|
66
|
+
# representing a column configuration, such as:
|
67
|
+
#
|
68
|
+
# {:name => :created_at, :header => "Created", :tooltip => "When the record was created"}
|
69
|
+
#
|
70
|
+
# This hash *overrides* (deep_merge) the hard-coded configuration, an example of which can be specifying
|
71
|
+
# columns for a GridPanel instance, e.g.:
|
72
|
+
#
|
73
|
+
# :columns => [{:name => :created_at, :sortable => false}]
|
74
|
+
#
|
75
|
+
# ... which in its turn overrides the defaults provided by persistent storage managed by the AttributesConfigurator
|
76
|
+
# that provides *model-level* (as opposed to a widget-level) configuration of a database model
|
77
|
+
# (which is used by both grids and forms in Netzke).
|
78
|
+
# And lastly, the defaults for AttributesConfigurator are calculated from the database model itself, powered by Netzke.
|
79
|
+
# For example, in the model you can specify virtual attributes and their types that will be picked up by Netzke, the default
|
80
|
+
# order of columns, or excluded columns. For details see <tt>Netzke::ActiveRecord::Attributes</tt>.
|
81
|
+
#
|
82
|
+
# The columns are displayed in the order specified by what's found first in the following sequence:
|
83
|
+
# GridPanel instance's persistent storage
|
84
|
+
# hardcoded config
|
85
|
+
# AttributesConfigurator persistent storage
|
86
|
+
# netzke_expose_attributes in the database model
|
87
|
+
# database columns + (eventually) virtual attributes specified with netzke_attribute
|
61
88
|
class GridPanel < Base
|
62
|
-
|
89
|
+
# javascript (client-side)
|
63
90
|
include GridPanelJs
|
64
|
-
|
91
|
+
|
92
|
+
# API (server-side)
|
65
93
|
include GridPanelApi
|
66
|
-
|
94
|
+
|
95
|
+
# Columns
|
96
|
+
include GridPanelColumns
|
97
|
+
|
98
|
+
# Code shared between GridPanel, FormPanel, and other widgets that serve as interface to database tables
|
67
99
|
include Netzke::DataAccessor
|
100
|
+
|
68
101
|
|
69
102
|
def self.enforce_config_consistency
|
70
103
|
config[:default_config][:ext_config][:enable_edit_in_form] &&= config[:edit_in_form_available]
|
@@ -111,24 +144,19 @@ module Netzke
|
|
111
144
|
# Checkcolumn
|
112
145
|
ext_examples = Netzke::Base.config[:ext_location] + "/examples/"
|
113
146
|
res << ext_examples + "ux/CheckColumn.js"
|
114
|
-
# res << "#{File.dirname(__FILE__)}/grid_panel/javascripts/check-column.js"
|
115
|
-
|
116
147
|
|
117
148
|
# Filters
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
# res << "#{File.dirname(__FILE__)}/grid_panel/javascripts/filters.js"
|
130
|
-
#
|
131
|
-
# end
|
149
|
+
if config[:column_filters_available]
|
150
|
+
ext_examples = Netzke::Base.config[:ext_location] + "/examples/"
|
151
|
+
res << ext_examples + "ux/gridfilters/menu/ListMenu.js"
|
152
|
+
res << ext_examples + "ux/gridfilters/menu/RangeMenu.js"
|
153
|
+
res << ext_examples + "ux/gridfilters/GridFilters.js"
|
154
|
+
|
155
|
+
%w{Boolean Date List Numeric String}.unshift("").each do |f|
|
156
|
+
res << ext_examples + "ux/gridfilters/filter/#{f}Filter.js"
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
132
160
|
|
133
161
|
# DD
|
134
162
|
if config[:rows_reordering_available]
|
@@ -137,7 +165,7 @@ module Netzke
|
|
137
165
|
|
138
166
|
res
|
139
167
|
end
|
140
|
-
|
168
|
+
|
141
169
|
# Define connection points between client side and server side of GridPanel.
|
142
170
|
# See implementation of equally named methods in the GridPanelApi module.
|
143
171
|
api :get_data, :post_data, :delete_data, :resize_column, :move_column, :hide_column, :get_combobox_options, :move_rows
|
@@ -147,9 +175,14 @@ module Netzke
|
|
147
175
|
|
148
176
|
# (We can't memoize this method because at some point we extend it, e.g. in Netzke::DataAccessor)
|
149
177
|
def data_class
|
150
|
-
|
151
|
-
|
152
|
-
|
178
|
+
@data_class ||= begin
|
179
|
+
klass = "Netzke::ModelExtensions::#{config[:model]}For#{short_widget_class_name}".constantize rescue nil
|
180
|
+
klass || begin
|
181
|
+
::ActiveSupport::Deprecation.warn("data_class_name option is deprecated. Use model instead", caller) if config[:data_class_name]
|
182
|
+
model_name = config[:model] || config[:data_class_name]
|
183
|
+
model_name.nil? ? raise(ArgumentError, "No model specified for widget #{global_id}") : model_name.constantize
|
184
|
+
end
|
185
|
+
end
|
153
186
|
end
|
154
187
|
|
155
188
|
def initialize(config = {}, parent = nil)
|
@@ -158,52 +191,31 @@ module Netzke
|
|
158
191
|
apply_helpers
|
159
192
|
end
|
160
193
|
|
161
|
-
#
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
{:name => :excluded, :type => :boolean, :editor => :checkbox, :width => 40, :header => "Excl"},
|
166
|
-
{:name => :value},
|
167
|
-
{:name => :header},
|
168
|
-
{:name => :hidden, :type => :boolean, :editor => :checkbox},
|
169
|
-
{:name => :editable, :type => :boolean, :editor => :checkbox, :header => "Editable", :default => true},
|
170
|
-
{:name => :editor, :type => :string, :editor => {:xtype => :combobox, :options => Netzke::Ext::FORM_FIELD_XTYPES}},
|
171
|
-
{:name => :renderer, :type => :string},
|
172
|
-
|
173
|
-
# maybe later
|
174
|
-
# {:name => :xtype, :type => :string, :editor => {:xtype => :combobox, :options => Netzke::Ext::COLUMN_XTYPES}},
|
175
|
-
|
176
|
-
# {:name => :renderer, :type => :string, :editor => {:xtype => :jsonfield}},
|
177
|
-
|
178
|
-
# Filters not supported in Ext 3.0
|
179
|
-
# {:name => :with_filters, :type => :boolean, :editor => :checkbox, :default => true, :header => "Filters"},
|
180
|
-
|
181
|
-
# some rarely used configurations, hidden
|
182
|
-
{:name => :width, :type => :integer, :editor => :numberfield, :hidden => true},
|
183
|
-
{:name => :hideable, :type => :boolean, :editor => :checkbox, :default => true, :hidden => true},
|
184
|
-
{:name => :sortable, :type => :boolean, :editor => :checkbox, :default => true, :hidden => true},
|
185
|
-
]
|
186
|
-
end
|
194
|
+
# def data_class
|
195
|
+
# klass = "Netzke::ModelExtensions::#{data_class.name}#{short_widget_class_name}Ext".constantize rescue nil
|
196
|
+
# klass || data_class
|
197
|
+
# end
|
187
198
|
|
199
|
+
# Fields to be displayed in the "General" tab of the configuration panel
|
188
200
|
def self.property_fields
|
189
201
|
res = [
|
190
202
|
{:name => :ext_config__title, :type => :string},
|
191
203
|
{:name => :ext_config__header, :type => :boolean, :default => true},
|
192
204
|
{:name => :ext_config__enable_context_menu, :type => :boolean, :default => true},
|
193
|
-
{:name => :ext_config__context_menu, :type => :json},
|
205
|
+
# {:name => :ext_config__context_menu, :type => :json},
|
194
206
|
{:name => :ext_config__enable_pagination, :type => :boolean, :default => true},
|
195
207
|
{:name => :ext_config__rows_per_page, :type => :integer},
|
196
|
-
{:name => :ext_config__bbar, :type => :json},
|
208
|
+
# {:name => :ext_config__bbar, :type => :json},
|
197
209
|
{:name => :ext_config__prohibit_create, :type => :boolean},
|
198
210
|
{:name => :ext_config__prohibit_update, :type => :boolean},
|
199
211
|
{:name => :ext_config__prohibit_delete, :type => :boolean},
|
200
212
|
{:name => :ext_config__prohibit_read, :type => :boolean}
|
201
213
|
]
|
202
214
|
|
203
|
-
res << {:name => :ext_config__enable_extended_search, :type => :boolean} if config[:extended_search_available]
|
204
|
-
res << {:name => :ext_config__enable_edit_in_form, :type => :boolean} if config[:edit_in_form_available]
|
215
|
+
# res << {:name => :ext_config__enable_extended_search, :type => :boolean} if config[:extended_search_available]
|
216
|
+
# res << {:name => :ext_config__enable_edit_in_form, :type => :boolean} if config[:edit_in_form_available]
|
205
217
|
|
206
|
-
# TODO: buggy thing
|
218
|
+
# TODO: a buggy thing
|
207
219
|
# res << {:name => :layout__columns, :type => :json}
|
208
220
|
|
209
221
|
res
|
@@ -237,9 +249,9 @@ module Netzke
|
|
237
249
|
res << {
|
238
250
|
:persistent_config => true,
|
239
251
|
:name => 'columns',
|
240
|
-
:class_name
|
252
|
+
:class_name => "FieldsConfigurator",
|
241
253
|
:active => true,
|
242
|
-
:
|
254
|
+
:owner => self
|
243
255
|
}
|
244
256
|
res << {
|
245
257
|
:name => 'general',
|
@@ -252,15 +264,30 @@ module Netzke
|
|
252
264
|
|
253
265
|
def actions
|
254
266
|
# Defaults
|
255
|
-
{
|
256
|
-
:add => {:text => 'Add',
|
257
|
-
:edit => {:text => 'Edit',
|
258
|
-
:del => {:text => 'Delete',
|
259
|
-
:apply => {:text => 'Apply',
|
260
|
-
:add_in_form => {:text => 'Add in form',
|
267
|
+
actions = {
|
268
|
+
:add => {:text => 'Add', :disabled => ext_config[:prohibit_create]},
|
269
|
+
:edit => {:text => 'Edit', :disabled => true},
|
270
|
+
:del => {:text => 'Delete', :disabled => true},
|
271
|
+
:apply => {:text => 'Apply', :disabled => ext_config[:prohibit_update] && ext_config[:prohibit_create]},
|
272
|
+
:add_in_form => {:text => 'Add in form', :disabled => !ext_config[:enable_edit_in_form]},
|
261
273
|
:edit_in_form => {:text => 'Edit in form', :disabled => true},
|
262
|
-
:search => {:text => 'Search',
|
274
|
+
:search => {:text => 'Search', :disabled => !ext_config[:enable_extended_search], :checked => true}
|
263
275
|
}
|
276
|
+
|
277
|
+
if Netzke::Base.config[:with_icons]
|
278
|
+
icons_uri = Netzke::Base.config[:icons_uri]
|
279
|
+
actions.deep_merge!(
|
280
|
+
:add => {:icon => icons_uri + "add.png"},
|
281
|
+
:edit => {:icon => icons_uri + "table_edit.png"},
|
282
|
+
:del => {:icon => icons_uri + "table_row_delete.png"},
|
283
|
+
:apply => {:icon => icons_uri + "tick.png"},
|
284
|
+
:add_in_form => {:icon => icons_uri + "application_form_add.png"},
|
285
|
+
:edit_in_form => {:icon => icons_uri + "application_form_edit.png"},
|
286
|
+
:search => {:icon => icons_uri + "find.png"}
|
287
|
+
)
|
288
|
+
end
|
289
|
+
|
290
|
+
actions
|
264
291
|
end
|
265
292
|
|
266
293
|
def initial_late_aggregatees
|
@@ -276,7 +303,7 @@ module Netzke
|
|
276
303
|
},
|
277
304
|
:item => {
|
278
305
|
:class_name => "FormPanel",
|
279
|
-
:model =>
|
306
|
+
:model => config[:model],
|
280
307
|
:persistent_config => config[:persistent_config],
|
281
308
|
:strong_default_attrs => config[:strong_default_attrs],
|
282
309
|
:ext_config => {
|
@@ -290,38 +317,50 @@ module Netzke
|
|
290
317
|
},
|
291
318
|
|
292
319
|
:edit_form => {
|
293
|
-
:class_name => "
|
294
|
-
:model => data_class.name,
|
295
|
-
:persistent_config => config[:persistent_config],
|
320
|
+
:class_name => "GridPanel::RecordFormWindow",
|
296
321
|
:ext_config => {
|
297
|
-
:
|
298
|
-
:
|
299
|
-
|
300
|
-
|
322
|
+
:title => "Edit #{data_class.name.humanize}",
|
323
|
+
:button_align => "right"
|
324
|
+
},
|
325
|
+
:item => {
|
326
|
+
:class_name => "FormPanel",
|
327
|
+
:model => config[:model],
|
328
|
+
:persistent_config => config[:persistent_config],
|
329
|
+
:ext_config => {
|
330
|
+
:bbar => false,
|
331
|
+
:header => false,
|
332
|
+
:mode => ext_config[:mode]
|
333
|
+
}
|
334
|
+
},
|
301
335
|
},
|
302
336
|
|
303
|
-
:
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
},
|
337
|
+
# :edit_form => {
|
338
|
+
# :class_name => "FormPanel",
|
339
|
+
# :model => data_class.name,
|
340
|
+
# :persistent_config => config[:persistent_config],
|
341
|
+
# :ext_config => {
|
342
|
+
# :bbar => false,
|
343
|
+
# :header => false,
|
344
|
+
# :mode => ext_config[:mode]
|
345
|
+
# }
|
346
|
+
# },
|
313
347
|
|
314
|
-
:
|
315
|
-
:class_name => "
|
316
|
-
:model => data_class.name,
|
317
|
-
:persistent_config => config[:persistent_config],
|
318
|
-
:strong_default_attrs => config[:strong_default_attrs],
|
348
|
+
:multi_edit_form => {
|
349
|
+
:class_name => "GridPanel::RecordFormWindow",
|
319
350
|
:ext_config => {
|
320
|
-
:
|
321
|
-
:
|
322
|
-
:mode => ext_config[:mode]
|
351
|
+
:title => "Edit #{data_class.name.humanize}",
|
352
|
+
:button_align => "right"
|
323
353
|
},
|
324
|
-
:
|
354
|
+
:item => {
|
355
|
+
:class_name => "FormPanel",
|
356
|
+
:model => config[:model],
|
357
|
+
:persistent_config => config[:persistent_config],
|
358
|
+
:ext_config => {
|
359
|
+
:bbar => false,
|
360
|
+
:header => false,
|
361
|
+
:mode => ext_config[:mode]
|
362
|
+
}
|
363
|
+
}
|
325
364
|
}
|
326
365
|
}) if ext_config[:enable_edit_in_form]
|
327
366
|
|
@@ -329,7 +368,7 @@ module Netzke
|
|
329
368
|
res.merge!({
|
330
369
|
:search_panel => {
|
331
370
|
:class_name => "SearchPanel",
|
332
|
-
:search_class_name =>
|
371
|
+
:search_class_name => config[:model],
|
333
372
|
:persistent_config => config[:persistent_config],
|
334
373
|
:ext_config => {
|
335
374
|
:header => false,
|
@@ -342,129 +381,7 @@ module Netzke
|
|
342
381
|
res
|
343
382
|
end
|
344
383
|
|
345
|
-
|
346
384
|
include Plugins::ConfigurationTool if config[:config_tool_available] # it will load ConfigurationPanel into a modal window
|
347
385
|
|
348
|
-
def columns
|
349
|
-
@columns ||= get_columns
|
350
|
-
end
|
351
|
-
|
352
|
-
# Normalized columns
|
353
|
-
def normalized_columns
|
354
|
-
@normalized_columns ||= normalize_columns(columns)
|
355
|
-
end
|
356
|
-
|
357
|
-
def get_columns
|
358
|
-
if persistent_config_enabled?
|
359
|
-
columns = persistent_config['layout__columns'] || default_columns
|
360
|
-
res = normalize_array_of_columns(columns)
|
361
|
-
else
|
362
|
-
res = default_columns
|
363
|
-
end
|
364
|
-
|
365
|
-
# denormalize
|
366
|
-
res.map{ |c| c.is_a?(Hash) && c.reject{ |k,v| k == :name }.empty? ? c[:name].to_sym : c }
|
367
|
-
end
|
368
|
-
|
369
|
-
# Normalizes the column at position +index+ and returns it.
|
370
|
-
def column_at(index)
|
371
|
-
if columns[index].is_a?(Hash)
|
372
|
-
columns[index]
|
373
|
-
else
|
374
|
-
column_name = columns.delete_at(index)
|
375
|
-
normalized_column = normalize_column(column_name)
|
376
|
-
columns.insert(index, normalized_column)
|
377
|
-
normalized_column
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
# Stores modified columns in persistent storage
|
382
|
-
def save_columns!
|
383
|
-
persistent_config[:layout__columns] = columns
|
384
|
-
end
|
385
|
-
|
386
|
-
TYPE_EDITOR_MAP = {
|
387
|
-
:integer => :numberfield,
|
388
|
-
:boolean => :checkbox,
|
389
|
-
:date => :datefield,
|
390
|
-
:datetime => :xdatetime,
|
391
|
-
:text => :textarea
|
392
|
-
# :string => :textfield
|
393
|
-
}
|
394
|
-
|
395
|
-
def default_columns
|
396
|
-
# columns specified in widget's config
|
397
|
-
columns_from_config = config[:columns] && normalize_columns(config[:columns])
|
398
|
-
|
399
|
-
if columns_from_config
|
400
|
-
# reverse-merge each column hash from config with each column hash from exposed_attributes (columns from config have higher priority)
|
401
|
-
for c in columns_from_config
|
402
|
-
corresponding_exposed_column = predefined_columns.find{ |k| k[:name] == c[:name] }
|
403
|
-
c.reverse_merge!(corresponding_exposed_column) if corresponding_exposed_column
|
404
|
-
end
|
405
|
-
columns_for_create = columns_from_config
|
406
|
-
else
|
407
|
-
# we didn't have columns configured in widget's config, so, use the columns from the data class
|
408
|
-
columns_for_create = predefined_columns
|
409
|
-
end
|
410
|
-
|
411
|
-
columns_for_create.map! do |c|
|
412
|
-
# detect ActiveRecord column type (if the column is "real") or fall back to :virtual
|
413
|
-
type = (data_class.columns_hash[c[:name].to_s] && data_class.columns_hash[c[:name].to_s].type) || :virtual
|
414
|
-
|
415
|
-
# detect :assoc__method columns
|
416
|
-
if c[:name].to_s.index('__')
|
417
|
-
assoc_name, method = c[:name].to_s.split('__').map(&:to_sym)
|
418
|
-
if assoc = data_class.reflect_on_association(assoc_name)
|
419
|
-
assoc_column = assoc.klass.columns_hash[method.to_s]
|
420
|
-
assoc_method_type = assoc_column.try(:type)
|
421
|
-
if assoc_method_type
|
422
|
-
c[:editor] ||= TYPE_EDITOR_MAP[assoc_method_type] == :checkbox ? :checkbox : :combobox
|
423
|
-
end
|
424
|
-
type = :association
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
# detect association column (e.g. :category_id)
|
429
|
-
assoc = data_class.reflect_on_all_associations.detect{|a| a.primary_key_name.to_sym == c[:name]}
|
430
|
-
if assoc && !assoc.options[:polymorphic]
|
431
|
-
c[:editor] ||= :combobox
|
432
|
-
assoc_method = %w{name title label id}.detect{|m| (assoc.klass.instance_methods + assoc.klass.column_names).include?(m) } || assoc.klass.primary_key
|
433
|
-
c[:name] = "#{assoc.name}__#{assoc_method}".to_sym
|
434
|
-
type = :association
|
435
|
-
end
|
436
|
-
|
437
|
-
# Some smart defaults
|
438
|
-
|
439
|
-
# default editor, dependent on column type
|
440
|
-
c[:editor] ||= TYPE_EDITOR_MAP[type] unless TYPE_EDITOR_MAP[type].nil?
|
441
|
-
# narrow column for checkbox
|
442
|
-
c[:width] ||= 50 if c[:editor] == :checkbox
|
443
|
-
# wider column for xdatetime
|
444
|
-
c[:width] ||= 120 if c[:editor] == :xdatetime
|
445
|
-
# hide ID column
|
446
|
-
c[:hidden] = true if c[:name] == data_class.primary_key.to_sym && c[:hidden].nil?
|
447
|
-
# make ID column read-only
|
448
|
-
c[:editable] = false if c[:name] == data_class.primary_key.to_sym && c[:editable].nil?
|
449
|
-
|
450
|
-
# Some default limitations for virtual columns
|
451
|
-
if type == :virtual
|
452
|
-
# disable filters
|
453
|
-
# c[:with_filters].nil? && c[:with_filters] = false
|
454
|
-
# disable sorting
|
455
|
-
c[:sortable].nil? && c[:sortable] = false
|
456
|
-
# read-only
|
457
|
-
# c[:read_only].nil? && c[:read_only] = true
|
458
|
-
c[:editable].nil? && c[:editable] = false
|
459
|
-
end
|
460
|
-
|
461
|
-
# denormalize column (save space)
|
462
|
-
c.reject{ |k,v| k == :name }.empty? ? c[:name] : c
|
463
|
-
end
|
464
|
-
|
465
|
-
columns_for_create
|
466
|
-
|
467
|
-
end
|
468
|
-
|
469
386
|
end
|
470
387
|
end
|