netzke-basepack 0.7.7 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +15 -10
- data/{CHANGELOG.rdoc → CHANGELOG.md} +146 -110
- data/LICENSE +7 -1
- data/README.md +47 -56
- data/Rakefile +5 -5
- data/config/before-travis.sh +10 -0
- data/javascripts/basepack.js +0 -130
- data/javascripts/netzkeremotecombo.js +59 -0
- data/lib/netzke/basepack.rb +9 -14
- data/lib/netzke/basepack/accordion.rb +45 -0
- data/lib/netzke/basepack/active_record.rb +12 -0
- data/lib/netzke/basepack/active_record/relation_extensions.rb +27 -0
- data/lib/netzke/basepack/columns.rb +309 -0
- data/lib/netzke/basepack/data_accessor.rb +22 -12
- data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +75 -11
- data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +154 -49
- data/lib/netzke/basepack/fields.rb +162 -0
- data/lib/netzke/basepack/form.rb +136 -0
- data/lib/netzke/basepack/{form_panel → form}/javascripts/comma_list_cbg.js +0 -1
- data/lib/netzke/basepack/{form_panel/javascripts/form_panel.js → form/javascripts/form.js} +20 -26
- data/lib/netzke/basepack/{form_panel → form}/javascripts/n_radio_group.js +0 -1
- data/lib/netzke/basepack/{form_panel → form}/javascripts/readonly_mode.js +0 -0
- data/lib/netzke/basepack/form/services.rb +115 -0
- data/lib/netzke/basepack/{form_panel → form}/stylesheets/readonly_mode.css +0 -0
- data/lib/netzke/basepack/grid.rb +355 -0
- data/lib/netzke/basepack/{grid_panel → grid}/javascripts/advanced_search.js +1 -1
- data/lib/netzke/basepack/{grid_panel → grid}/javascripts/check_column_fix.js +0 -0
- data/lib/netzke/basepack/{grid_panel → grid}/javascripts/edit_in_form.js +3 -3
- data/lib/netzke/basepack/{grid_panel → grid}/javascripts/event_handling.js +5 -2
- data/lib/netzke/basepack/{grid_panel/javascripts/grid_panel.js → grid/javascripts/grid.js} +120 -132
- data/lib/netzke/basepack/{grid_panel → grid}/javascripts/misc.js +0 -0
- data/lib/netzke/basepack/grid/services.rb +216 -0
- data/lib/netzke/basepack/item_persistence.rb +44 -0
- data/lib/netzke/basepack/item_persistence/events_plugin.rb +47 -0
- data/lib/netzke/basepack/{paging_form_panel.rb → paging_form.rb} +24 -30
- data/lib/netzke/basepack/{paging_form_panel/javascripts/paging_form_panel.js → paging_form/javascripts/paging_form.js} +2 -4
- data/lib/netzke/basepack/query_builder.rb +44 -73
- data/lib/netzke/basepack/query_builder/javascripts/query_builder.js +16 -2
- data/lib/netzke/basepack/record_form_window.rb +67 -0
- data/lib/netzke/basepack/search_panel.rb +22 -24
- data/lib/netzke/basepack/search_panel/javascripts/condition_field.js +2 -2
- data/lib/netzke/basepack/search_window.rb +47 -53
- data/lib/netzke/basepack/simple_app.rb +10 -13
- data/lib/netzke/basepack/simple_app/javascripts/simple_app.js +2 -8
- data/lib/netzke/basepack/tab_panel.rb +5 -4
- data/lib/netzke/basepack/tab_panel/javascripts/tab_panel.js +5 -5
- data/lib/netzke/basepack/version.rb +2 -2
- data/lib/netzke/basepack/viewport.rb +16 -0
- data/lib/netzke/basepack/window.rb +27 -18
- data/lib/netzke/basepack/window/javascripts/window.js +7 -1
- data/lib/netzke/basepack/wrap_lazy_loaded.rb +18 -18
- data/locales/en.yml +40 -24
- data/netzke-basepack.gemspec +51 -82
- data/stylesheets/basepack.css +0 -41
- data/test/basepack_test_app/Gemfile +9 -46
- data/test/basepack_test_app/Gemfile.lock +61 -96
- data/test/basepack_test_app/app/components/author_form.rb +8 -5
- data/test/basepack_test_app/app/components/author_grid.rb +2 -2
- data/test/basepack_test_app/app/components/book_form.rb +34 -31
- data/test/basepack_test_app/app/components/book_form_with_defaults.rb +6 -7
- data/test/basepack_test_app/app/components/book_form_with_file_upload.rb +10 -0
- data/test/basepack_test_app/app/components/book_form_with_nested_attributes.rb +5 -6
- data/test/basepack_test_app/app/components/book_grid.rb +19 -8
- data/test/basepack_test_app/app/components/book_grid_filtering.rb +4 -7
- data/test/basepack_test_app/app/components/book_grid_loader.rb +28 -15
- data/test/basepack_test_app/app/components/book_grid_with_custom_columns.rb +45 -21
- data/test/basepack_test_app/app/components/book_grid_with_default_values.rb +26 -8
- data/test/basepack_test_app/app/components/book_grid_with_excluded_columns.rb +11 -0
- data/test/basepack_test_app/app/components/book_grid_with_extra_feedback.rb +2 -2
- data/test/basepack_test_app/app/components/book_grid_with_extra_filters.rb +7 -6
- data/test/basepack_test_app/app/components/book_grid_with_mass_assignment_security.rb +9 -0
- data/test/basepack_test_app/app/components/book_grid_with_nested_attributes.rb +9 -9
- data/test/basepack_test_app/app/components/book_grid_with_overridden_columns.rb +5 -3
- data/test/basepack_test_app/app/components/book_grid_with_paging.rb +6 -8
- data/test/basepack_test_app/app/components/book_grid_with_persistence.rb +6 -4
- data/test/basepack_test_app/app/components/book_grid_with_scope.rb +6 -0
- data/test/basepack_test_app/app/components/book_grid_with_scoped_authors.rb +10 -7
- data/test/basepack_test_app/app/components/book_grid_with_virtual_attributes.rb +21 -13
- data/test/basepack_test_app/app/components/book_paging_form.rb +21 -0
- data/test/basepack_test_app/app/components/book_query_builder.rb +7 -6
- data/test/basepack_test_app/app/components/book_with_custom_primary_key_grid.rb +6 -7
- data/test/basepack_test_app/app/components/books_bound_to_author.rb +9 -7
- data/test/basepack_test_app/app/components/border_layout_panel_with_persistence.rb +12 -0
- data/test/basepack_test_app/app/components/double_book_grid.rb +19 -14
- data/test/basepack_test_app/app/components/form_without_model.rb +15 -16
- data/test/basepack_test_app/app/components/grid_with_initial_sorting.rb +7 -0
- data/test/basepack_test_app/app/components/grid_with_inline_data.rb +7 -0
- data/test/basepack_test_app/app/components/paging_form_with_search.rb +2 -2
- data/test/basepack_test_app/app/components/panel_with_persistent_regions.rb +35 -0
- data/test/basepack_test_app/app/components/query_builder.rb +7 -0
- data/test/basepack_test_app/app/components/simple_panel.rb +16 -11
- data/test/basepack_test_app/app/components/simple_window.rb +7 -6
- data/test/basepack_test_app/app/components/some_accordion.rb +18 -0
- data/test/basepack_test_app/app/components/some_auth_app.rb +5 -5
- data/test/basepack_test_app/app/components/some_border_layout.rb +20 -20
- data/test/basepack_test_app/app/components/some_search_panel.rb +6 -0
- data/test/basepack_test_app/app/components/some_simple_app.rb +30 -16
- data/test/basepack_test_app/app/components/some_tab_panel.rb +18 -15
- data/test/basepack_test_app/app/components/user_form.rb +18 -16
- data/test/basepack_test_app/app/components/user_form_with_default_fields.rb +5 -6
- data/test/basepack_test_app/app/components/user_grid.rb +11 -6
- data/test/basepack_test_app/app/components/user_grid_with_customized_form_fields.rb +5 -3
- data/test/basepack_test_app/app/components/window_component_loader.rb +25 -21
- data/test/basepack_test_app/app/models/address.rb +0 -26
- data/test/basepack_test_app/app/models/author.rb +0 -31
- data/test/basepack_test_app/app/models/book.rb +1 -42
- data/test/basepack_test_app/app/models/book_with_custom_primary_key.rb +1 -23
- data/test/basepack_test_app/app/models/role.rb +0 -21
- data/test/basepack_test_app/app/models/user.rb +0 -24
- data/test/basepack_test_app/app/views/layouts/components.html.erb +1 -1
- data/test/basepack_test_app/config/application.rb +1 -1
- data/test/basepack_test_app/config/database.yml.travis +2 -6
- data/test/basepack_test_app/config/initializers/netzke.rb +1 -6
- data/test/basepack_test_app/db/schema.rb +14 -14
- data/test/basepack_test_app/features/accordion_panel.feature +2 -2
- data/test/basepack_test_app/features/form_panel.feature +7 -7
- data/test/basepack_test_app/features/grid_panel.feature +93 -39
- data/test/basepack_test_app/features/grid_panel_with_custom_primary_key.feature +2 -1
- data/test/basepack_test_app/features/grid_sorting.feature +30 -6
- data/test/basepack_test_app/features/paging_form_panel.feature +7 -7
- data/test/basepack_test_app/features/persistent_regions.feature +30 -0
- data/test/basepack_test_app/features/search_in_grid.feature +5 -5
- data/test/basepack_test_app/features/simple_app.feature +6 -7
- data/test/basepack_test_app/features/step_definitions/form_panel_steps.rb +1 -1
- data/test/basepack_test_app/features/step_definitions/generic_steps.rb +109 -4
- data/test/basepack_test_app/features/step_definitions/grid_panel_steps.rb +8 -10
- data/test/basepack_test_app/features/step_definitions/window_steps.rb +27 -0
- data/test/basepack_test_app/features/tab_panel.feature +1 -1
- data/test/basepack_test_app/features/window.feature +17 -0
- data/test/unit/accordion_panel_test.rb +2 -2
- data/test/unit/grid_panel_test.rb +4 -4
- metadata +57 -83
- data/TODO.rdoc +0 -8
- data/lib/generators/netzke/basepack_generator.rb +0 -10
- data/lib/generators/netzke/templates/assets/ts-checkbox.gif +0 -0
- data/lib/generators/netzke/templates/create_netzke_field_lists.rb +0 -18
- data/lib/netzke/active_record.rb +0 -20
- data/lib/netzke/active_record/attributes.rb +0 -259
- data/lib/netzke/active_record/combobox_options.rb +0 -16
- data/lib/netzke/active_record/relation_extensions.rb +0 -37
- data/lib/netzke/basepack/accordion_panel.rb +0 -39
- data/lib/netzke/basepack/action_column.rb +0 -68
- data/lib/netzke/basepack/action_column/javascripts/action_column.js +0 -61
- data/lib/netzke/basepack/auth_app.rb +0 -159
- data/lib/netzke/basepack/basic_app.rb +0 -7
- data/lib/netzke/basepack/border_layout_panel.rb +0 -53
- data/lib/netzke/basepack/border_layout_panel/javascripts/border_layout_panel.js +0 -40
- data/lib/netzke/basepack/data_adapters/data_mapper_adapter.rb +0 -264
- data/lib/netzke/basepack/data_adapters/sequel_adapter.rb +0 -260
- data/lib/netzke/basepack/form_panel.rb +0 -144
- data/lib/netzke/basepack/form_panel/fields.rb +0 -208
- data/lib/netzke/basepack/form_panel/javascripts/misc.js +0 -4
- data/lib/netzke/basepack/form_panel/services.rb +0 -142
- data/lib/netzke/basepack/grid_panel.rb +0 -441
- data/lib/netzke/basepack/grid_panel/columns.rb +0 -400
- data/lib/netzke/basepack/grid_panel/javascripts/rows-dd.js +0 -281
- data/lib/netzke/basepack/grid_panel/record_form_window.rb +0 -41
- data/lib/netzke/basepack/grid_panel/services.rb +0 -235
- data/lib/netzke/basepack/panel.rb +0 -11
- data/lib/netzke/basepack/wrapper.rb +0 -28
- data/lib/netzke/data_mapper.rb +0 -18
- data/lib/netzke/data_mapper/attributes.rb +0 -273
- data/lib/netzke/data_mapper/combobox_options.rb +0 -11
- data/lib/netzke/data_mapper/relation_extensions.rb +0 -38
- data/lib/netzke/sequel.rb +0 -18
- data/lib/netzke/sequel/attributes.rb +0 -274
- data/lib/netzke/sequel/combobox_options.rb +0 -10
- data/lib/netzke/sequel/relation_extensions.rb +0 -40
- data/locales/zh-cn.yml +0 -79
- data/test/basepack_test_app/app/components/book_form_with_custom_fields.rb +0 -21
- data/test/basepack_test_app/app/components/book_grid_with_column_actions.rb +0 -15
- data/test/basepack_test_app/app/components/book_grid_with_defaults.rb +0 -6
- data/test/basepack_test_app/app/components/book_paging_form_panel.rb +0 -22
- data/test/basepack_test_app/app/components/generic_user_form.rb +0 -12
- data/test/basepack_test_app/app/components/simple_accordion.rb +0 -11
- data/test/basepack_test_app/app/components/simple_tab_panel.rb +0 -11
- data/test/basepack_test_app/app/components/simple_wrapper.rb +0 -7
- data/test/basepack_test_app/app/components/some_accordion_panel.rb +0 -22
- data/test/basepack_test_app/app/presenters/forms/generic_user.rb +0 -6
- data/test/basepack_test_app/app/views/components/loadable_window.html.erb +0 -9
- data/test/basepack_test_app/app/views/components/simple_panel.html.erb +0 -1
- data/test/basepack_test_app/features/components_in_view.feature +0 -11
- data/test/basepack_test_app/features/simple_panel.feature +0 -11
- data/test/basepack_test_app/features/validations_in_grid.feature +0 -13
- data/test/basepack_test_app/features/virtual_attributes.feature +0 -16
- data/test/basepack_test_app/spec/components/form_panel_spec.rb +0 -53
- data/test/basepack_test_app/spec/components/grid_panel_spec.rb +0 -10
- data/test/basepack_test_app/spec/data_adapter/adapter_spec.rb +0 -68
- data/test/basepack_test_app/spec/data_adapter/attributes_spec.rb +0 -56
- data/test/basepack_test_app/spec/data_adapter/relation_extensions_spec.rb +0 -125
- data/test/basepack_test_app/spec/factories.rb +0 -28
- data/test/basepack_test_app/spec/spec_helper.rb +0 -39
@@ -1,260 +0,0 @@
|
|
1
|
-
module Netzke::Basepack::DataAdapters
|
2
|
-
class SequelAdapter < AbstractAdapter
|
3
|
-
def self.for_class?(model_class)
|
4
|
-
model_class <= Sequel::Model
|
5
|
-
end
|
6
|
-
|
7
|
-
def get_records(params, columns=[])
|
8
|
-
get_dataset(params, columns).all
|
9
|
-
end
|
10
|
-
|
11
|
-
def count_records(params, columns=[])
|
12
|
-
# dont pass columns, JOINs will be done as necessary for filters
|
13
|
-
get_dataset(params, [], true).count
|
14
|
-
end
|
15
|
-
|
16
|
-
def map_type type
|
17
|
-
type
|
18
|
-
end
|
19
|
-
|
20
|
-
def get_assoc_property_type assoc_name, prop_name
|
21
|
-
db_schema=class_for(assoc_name.to_sym).db_schema
|
22
|
-
# return nil if prop_name not present in db schema (virtual column)
|
23
|
-
db_schema[prop_name.to_sym] ? db_schema[prop_name.to_sym][:type] : nil
|
24
|
-
end
|
25
|
-
|
26
|
-
# like get_assoc_property_type but for non-association columns
|
27
|
-
def get_property_type column
|
28
|
-
column[:type]
|
29
|
-
end
|
30
|
-
|
31
|
-
def column_virtual? c
|
32
|
-
assoc, method = c[:name].split '__'
|
33
|
-
if method
|
34
|
-
!class_for(assoc.to_sym).columns.include? method.to_sym
|
35
|
-
else
|
36
|
-
!@model_class.columns.include? assoc.to_sym
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Returns options for comboboxes in grids/forms
|
41
|
-
def combobox_options_for_column(column, method_options = {})
|
42
|
-
query = method_options[:query]
|
43
|
-
|
44
|
-
# First, check if we have options for this column defined in persistent storage
|
45
|
-
options = column[:combobox_options] && column[:combobox_options].split("\n")
|
46
|
-
if options
|
47
|
-
query ? options.select{ |o| o.index(/^#{query}/) }.map{ |el| [el] } : options
|
48
|
-
else
|
49
|
-
assoc_name, assoc_method = column[:name].split '__'
|
50
|
-
|
51
|
-
if assoc_name
|
52
|
-
# Options for an asssociation attribute
|
53
|
-
dataset = class_for(assoc_name)
|
54
|
-
|
55
|
-
dataset = dataset.extend_with(method_options[:scope]) if method_options[:scope]
|
56
|
-
|
57
|
-
if class_for(assoc_name).column_names.include?(assoc_method)
|
58
|
-
# apply query
|
59
|
-
dataset = dataset.where(assoc_method.to_sym.like("%#{query}%")) if query.present?
|
60
|
-
dataset.all.map{ |r| [r.id, r.send(assoc_method)] }
|
61
|
-
else
|
62
|
-
dataset.all.map{ |r| [r.id, r.send(assoc_method)] }.select{ |id,value| value =~ /^#{query}/ }
|
63
|
-
end
|
64
|
-
else
|
65
|
-
# Options for a non-association attribute
|
66
|
-
res=@model_class.netzke_combo_options_for(column[:name], method_options)
|
67
|
-
|
68
|
-
# ensure it is an array-in-array, as Ext will fail otherwise
|
69
|
-
raise RuntimeError, "netzke_combo_options_for should return an Array" unless res.kind_of? Array
|
70
|
-
return [[]] if res.empty?
|
71
|
-
|
72
|
-
unless res.first.kind_of? Array
|
73
|
-
res=res.map do |v|
|
74
|
-
[v]
|
75
|
-
end
|
76
|
-
end
|
77
|
-
return res
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def foreign_key_for assoc_name
|
83
|
-
@model_class.association_reflection(assoc_name.to_sym)[:key].to_s
|
84
|
-
end
|
85
|
-
|
86
|
-
# Returns the model class for an association
|
87
|
-
def class_for assoc_name
|
88
|
-
@model_class.association_reflection(assoc_name.to_sym)[:class_name].constantize
|
89
|
-
end
|
90
|
-
|
91
|
-
def destroy(ids)
|
92
|
-
@model_class.where(:id => ids).destroy
|
93
|
-
end
|
94
|
-
|
95
|
-
def find_record(id)
|
96
|
-
@model_class[id]
|
97
|
-
end
|
98
|
-
|
99
|
-
# Build a hash of foreign keys and the associated model
|
100
|
-
def hash_fk_model
|
101
|
-
@model_class.all_association_reflections.inject({}) do |res, assoc|
|
102
|
-
res[assoc[:key]] = assoc[:class_name].constantize.model_name.underscore.to_sym
|
103
|
-
res
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# TODO: is this possible with Sequel?
|
108
|
-
def move_records(params)
|
109
|
-
end
|
110
|
-
|
111
|
-
# give the data adapter the opportunity the set special options for
|
112
|
-
# saving
|
113
|
-
def save_record(record)
|
114
|
-
# don't raise an error on saving. basepack will evaluate record.errors
|
115
|
-
# to get validation errors
|
116
|
-
record.raise_on_save_failure = false
|
117
|
-
record.save
|
118
|
-
end
|
119
|
-
|
120
|
-
# give the data adapter the opporunity to process error messages
|
121
|
-
# must return an raay of the form ["Title can't be blank", "Foo can't be blank"]
|
122
|
-
def errors_array(record)
|
123
|
-
record.errors.to_a.inject([]) do |errors, error|
|
124
|
-
field, message = error
|
125
|
-
errors << "#{record.class.human_attribute_name(field)} #{message.join ', '}"
|
126
|
-
errors
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# Needed for seed and tests
|
131
|
-
def last
|
132
|
-
@model_class.last
|
133
|
-
end
|
134
|
-
|
135
|
-
# Needed for seed and tests
|
136
|
-
def destroy_all
|
137
|
-
@model_class.destroy
|
138
|
-
end
|
139
|
-
|
140
|
-
private
|
141
|
-
def get_dataset params, columns, for_count=false
|
142
|
-
dataset = @model_class
|
143
|
-
|
144
|
-
graphed=[]
|
145
|
-
|
146
|
-
# Parses and applies grid column filters
|
147
|
-
#
|
148
|
-
# Example column grid data:
|
149
|
-
#
|
150
|
-
# {"0" => {
|
151
|
-
# "data" => {
|
152
|
-
# "type" => "numeric",
|
153
|
-
# "comparison" => "gt",
|
154
|
-
# "value" => 10 },
|
155
|
-
# "field" => "id"
|
156
|
-
# },
|
157
|
-
# "1" => {
|
158
|
-
# "data" => {
|
159
|
-
# "type" => "string",
|
160
|
-
# "value" => "pizza"
|
161
|
-
# },
|
162
|
-
# "field" => "food_name"
|
163
|
-
# }}
|
164
|
-
#
|
165
|
-
|
166
|
-
if params[:filter]
|
167
|
-
# these are still JSON-encoded due to the migration to Ext.direct
|
168
|
-
column_filter=JSON.parse(params[:filter])
|
169
|
-
|
170
|
-
column_filter.each do |v|
|
171
|
-
field = v["field"]
|
172
|
-
assoc, method = field.split('__')
|
173
|
-
if method
|
174
|
-
# when filtering on association's columns, we need to graph for LEFT OUTER JOIN
|
175
|
-
dataset = dataset.eager_graph assoc.to_sym unless graphed.include? assoc.to_sym
|
176
|
-
graphed << assoc.to_sym
|
177
|
-
end
|
178
|
-
|
179
|
-
value = v["value"]
|
180
|
-
type = v["type"]
|
181
|
-
op = v["comparison"]
|
182
|
-
|
183
|
-
if type == "string"
|
184
|
-
# strings are always LIKEd (case-insensitive)
|
185
|
-
dataset = dataset.filter field.to_sym.ilike("%#{value}%")
|
186
|
-
else
|
187
|
-
if type == "date"
|
188
|
-
# convert value to the DB date
|
189
|
-
value.match /(\d\d)\/(\d\d)\/(\d\d\d\d)/
|
190
|
-
value = "#{$3}-#{$1}-#{$2}"
|
191
|
-
end
|
192
|
-
# if it's NOT an association column, we need to qualify column name with model's table_name
|
193
|
-
qualified_column_name = method ? field.to_sym : field.to_sym.qualify(@model_class.table_name)
|
194
|
-
case op
|
195
|
-
when 'lt'
|
196
|
-
dataset = dataset.filter ":column < '#{value}'", :column => qualified_column_name
|
197
|
-
when 'gt'
|
198
|
-
dataset = dataset.filter ":column > '#{value}'", :column => qualified_column_name
|
199
|
-
else
|
200
|
-
dataset = dataset.filter qualified_column_name => value
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
# skip sorting, eager joining and paging if dataset is used for count
|
206
|
-
unless for_count
|
207
|
-
if params[:sort] && sort_params = params[:sort]
|
208
|
-
sort_params.each do |sort_param|
|
209
|
-
assoc, method = sort_param["property"].split("__")
|
210
|
-
dir = sort_param["direction"].downcase
|
211
|
-
|
212
|
-
# if a sorting scope is set, call the scope with the given direction
|
213
|
-
column = columns.detect { |c| c[:name] == sort_param["property"] }
|
214
|
-
if column.try(:'has_key?', :sorting_scope)
|
215
|
-
dataset = dataset.send(column[:sorting_scope].to_sym, dir.to_sym)
|
216
|
-
else
|
217
|
-
if method # sorting on associations column
|
218
|
-
# graph the association for LEFT OUTER JOIN
|
219
|
-
dataset = dataset.eager_graph(assoc.to_sym) unless graphed.include? assoc.to_sym
|
220
|
-
graphed << assoc.to_sym
|
221
|
-
end
|
222
|
-
# coincidentally, netzkes convention of specifying association's attributes
|
223
|
-
# i.e. "author__name" on Book matches sequel's convention
|
224
|
-
# so we can just pass symbolized property here
|
225
|
-
dataset = dataset.order(sort_param["property"].to_sym.send(dir))
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
# eager load the associations indicated by columns,
|
231
|
-
# but only if we didn't eager_graph them before (for ordering/filtering)
|
232
|
-
# because this saves a ID IN query
|
233
|
-
columns.each do |column|
|
234
|
-
if column[:name].index('__')
|
235
|
-
assoc, _ = column[:name].split('__')
|
236
|
-
dataset = dataset.eager(assoc.to_sym) unless graphed.include? assoc.to_sym
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
# apply paging
|
241
|
-
if params[:limit]
|
242
|
-
if params[:start]
|
243
|
-
dataset = dataset.limit params[:limit], params[:start]
|
244
|
-
else
|
245
|
-
dataset = dataset.limit params[:limit]
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
# apply scope
|
251
|
-
# need to symbolize_keys, because when the request is made from client-side (as opposed
|
252
|
-
# to server-side on inital render), the scope's keys are given as string {"author_id" => 1}
|
253
|
-
# If we give Sequel a filter like this, it will (correctly) do WHERE 'author_id' = 1 - note the quotes
|
254
|
-
# making the database match the string author_id to 1 and to the column.
|
255
|
-
dataset = dataset.extend_with(params[:scope].symbolize_keys) if params[:scope]
|
256
|
-
dataset
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
end
|
@@ -1,144 +0,0 @@
|
|
1
|
-
require "netzke/basepack/form_panel/fields"
|
2
|
-
require "netzke/basepack/form_panel/services"
|
3
|
-
# require "netzke/plugins/configuration_tool"
|
4
|
-
|
5
|
-
module Netzke
|
6
|
-
module Basepack
|
7
|
-
# Ext.form.Panel-based component
|
8
|
-
#
|
9
|
-
# == Netzke-specific config options
|
10
|
-
#
|
11
|
-
# * +model+ - name of the ActiveRecord model that provides data to this GridPanel.
|
12
|
-
# * +record+ - record to be displayd in the form. Takes precedence over +:record_id+
|
13
|
-
# * +record_id+ - id of the record to be displayd in the form. Also see +:record+
|
14
|
-
# * +items+ - the layout of the fields as an array. See "Layout configuration".
|
15
|
-
# * +mode+ - render mode, accepted options:
|
16
|
-
# * +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
|
17
|
-
# * +updateMask+ - +Ext.LoadMask+ config options for the mask shown while the form is submitting its values
|
18
|
-
#
|
19
|
-
# === Layout configuration
|
20
|
-
#
|
21
|
-
# 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). FormPanel will expand fields by looking at their names (unless +no_binding+ set to +true+ is specified for a specific field).
|
22
|
-
#
|
23
|
-
# == Endpoints
|
24
|
-
# FormPanel implements the following endpoints:
|
25
|
-
#
|
26
|
-
# * +netzke_load+ - loads a record with a given id from the server, e.g.:
|
27
|
-
#
|
28
|
-
# someFormPanel.netzkeLoad({id: 100});
|
29
|
-
#
|
30
|
-
# * +netzke_submit+ - gets called when the form gets submitted (e.g. by pressing the Apply button, or by calling onApply)
|
31
|
-
# * +get_combobox_options+ - gets called when a 'remote' combobox field gets expanded
|
32
|
-
class FormPanel < Netzke::Base
|
33
|
-
|
34
|
-
js_base_class "Ext.form.Panel"
|
35
|
-
|
36
|
-
# Class-level configuration
|
37
|
-
class_attribute :config_tool_available
|
38
|
-
self.config_tool_available = true
|
39
|
-
|
40
|
-
include self::Services
|
41
|
-
include self::Fields
|
42
|
-
include Netzke::Basepack::DataAccessor
|
43
|
-
|
44
|
-
delegates_to_dsl :model, :record_id
|
45
|
-
|
46
|
-
action :apply do
|
47
|
-
{
|
48
|
-
:text => I18n.t('netzke.basepack.form_panel.actions.apply'),
|
49
|
-
:tooltip => I18n.t('netzke.basepack.form_panel.actions.apply_tooltip'),
|
50
|
-
:icon => :tick
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
action :edit do
|
55
|
-
{
|
56
|
-
:text => I18n.t('netzke.basepack.form_panel.actions.edit'),
|
57
|
-
:tooltip => I18n.t('netzke.basepack.form_panel.actions.edit_tooltip'),
|
58
|
-
:icon => :pencil
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
action :cancel do
|
63
|
-
{
|
64
|
-
:text => I18n.t('netzke.basepack.form_panel.actions.cancel'),
|
65
|
-
:tooltip => I18n.t('netzke.basepack.form_panel.actions.cancel_tooltip'),
|
66
|
-
:icon => :cancel
|
67
|
-
}
|
68
|
-
end
|
69
|
-
|
70
|
-
def configuration
|
71
|
-
super.tap do |sup|
|
72
|
-
configure_locked(sup)
|
73
|
-
configure_bbar(sup)
|
74
|
-
|
75
|
-
sup[:record_id] = sup[:record] = nil if sup[:multi_edit] # never set record_id in multi-edit mode
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def configure_locked(c)
|
80
|
-
c[:locked] = c[:locked].nil? ? (c[:mode] == :lockable) : c[:locked]
|
81
|
-
end
|
82
|
-
|
83
|
-
def configure_bbar(c)
|
84
|
-
c[:bbar] = [:apply.action] if c[:bbar].nil? && !c[:read_only]
|
85
|
-
end
|
86
|
-
|
87
|
-
# Extra JavaScripts and stylesheets
|
88
|
-
js_mixin :form_panel
|
89
|
-
js_include :comma_list_cbg
|
90
|
-
js_include :n_radio_group, :readonly_mode
|
91
|
-
css_include :readonly_mode
|
92
|
-
|
93
|
-
# WIP
|
94
|
-
# js_include Netzke::Core.ext_path.join("examples/ux/fileuploadfield/FileUploadField.js")
|
95
|
-
# css_include Netzke::Core.ext_path.join("examples/ux/fileuploadfield/css/fileuploadfield.css")
|
96
|
-
|
97
|
-
# WIP: Needed for FileUploadField
|
98
|
-
# js_include :misc
|
99
|
-
|
100
|
-
def js_config
|
101
|
-
super.tap do |res|
|
102
|
-
res[:pri] = data_class && data_class.primary_key.to_s
|
103
|
-
res[:record] = js_record_data if record
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# A hash of record data including the meta field
|
108
|
-
def js_record_data
|
109
|
-
record.netzke_hash(fields).merge(:meta => meta_field).literalize_keys
|
110
|
-
end
|
111
|
-
|
112
|
-
def record
|
113
|
-
@record ||= config[:record] || config[:record_id] && data_class && data_adapter.find_record(config[:record_id])
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
def self.server_side_config_options
|
119
|
-
super + [:record, :scope]
|
120
|
-
end
|
121
|
-
|
122
|
-
def meta_field
|
123
|
-
{}.tap do |res|
|
124
|
-
assoc_values = get_association_values
|
125
|
-
res[:association_values] = assoc_values.literalize_keys if record && !assoc_values.empty?
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def get_association_values
|
130
|
-
fields_that_need_associated_values = fields.select{ |k,v| k.to_s.index("__") && !fields[k][:nested_attribute] }
|
131
|
-
# Take care of Ruby 1.8.7
|
132
|
-
if fields_that_need_associated_values.is_a?(Array)
|
133
|
-
fields_that_need_associated_values = fields_that_need_associated_values.inject({}){|r,(k,v)| r.merge(k => v)}
|
134
|
-
end
|
135
|
-
|
136
|
-
fields_that_need_associated_values.each_pair.inject({}) do |r,(k,v)|
|
137
|
-
r.merge(k => record.value_for_attribute(fields_that_need_associated_values[k], true))
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
# include ::Netzke::Plugins::ConfigurationTool if config_tool_available # it will load ConfigurationPanel into a modal window
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
@@ -1,208 +0,0 @@
|
|
1
|
-
module Netzke
|
2
|
-
module Basepack
|
3
|
-
class FormPanel < Netzke::Base
|
4
|
-
# Because FormPanel allows for arbitrary layout of fields, we need to have all fields configured in one place (the +fields+ method), and then have references to those fields from +items+.
|
5
|
-
module Fields
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
# Items with normalized fields (i.e. containing all the necessary attributes needed by Ext.form.FormPanel to render a field)
|
9
|
-
def items
|
10
|
-
@form_panel_items ||= begin
|
11
|
-
res = normalize_fields(super || data_class && data_class.netzke_attributes || []) # netzke_attributes as default items
|
12
|
-
# if primary key isn't there, insert it as first
|
13
|
-
if data_class && !res.detect{ |f| f[:name] == data_class.primary_key.to_s}
|
14
|
-
primary_key_item = normalize_field(data_class.primary_key.to_sym)
|
15
|
-
@fields_from_config[data_class.primary_key.to_sym] = primary_key_item
|
16
|
-
res.insert(0, primary_key_item)
|
17
|
-
end
|
18
|
-
res
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Hash of fully configured fields, that are referenced in the items. E.g.:
|
23
|
-
# {
|
24
|
-
# :role__name => {:xtype => 'netzkeremotecombo', :disabled => true, :value => "admin"},
|
25
|
-
# :created_at => {:xtype => 'datetime', :disabled => true, :value => "2010-10-10 10:10"}
|
26
|
-
# }
|
27
|
-
def fields
|
28
|
-
@fields ||= begin
|
29
|
-
if static_layout?
|
30
|
-
# extract incomplete field configs from +config+
|
31
|
-
flds = fields_from_config
|
32
|
-
# and merged them with fields from the model
|
33
|
-
deep_merge_existing_fields(flds, fields_from_model) if data_class
|
34
|
-
else
|
35
|
-
# extract flds configs from the model
|
36
|
-
flds = fields_from_model
|
37
|
-
end
|
38
|
-
flds
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# The array of fields as specified on the model level (using +netzke_attribute+ and alike)
|
43
|
-
def fields_array_from_model
|
44
|
-
data_class && data_class.netzke_attributes
|
45
|
-
end
|
46
|
-
|
47
|
-
# Hash of fields as specified on the model level
|
48
|
-
def fields_from_model
|
49
|
-
@fields_from_model ||= fields_array_from_model && fields_array_from_model.inject({}){ |hsh, f| hsh.merge(f[:name].to_sym => f) }
|
50
|
-
end
|
51
|
-
|
52
|
-
# Hash of normalized field configs extracted from :items, e.g.:
|
53
|
-
#
|
54
|
-
# {:role__name => {:xtype => "netzkeremotecombo"}, :password => {:xtype => "passwordfield"}}
|
55
|
-
def fields_from_config
|
56
|
-
items if @fields_from_config.nil? # by calling +items+ we initiate building of @fields_from_config
|
57
|
-
@fields_from_config ||= {}
|
58
|
-
end
|
59
|
-
|
60
|
-
module ClassMethods
|
61
|
-
# Columns to be displayed by the FieldConfigurator, "meta-columns". Each corresponds to a configuration
|
62
|
-
# option for each field in the form.
|
63
|
-
def meta_columns
|
64
|
-
[
|
65
|
-
{:name => "included", :attr_type => :boolean, :width => 40, :header => "Incl", :default_value => true},
|
66
|
-
{:name => "name", :attr_type => :string, :editor => :netzkeremotecombo, :width => 200},
|
67
|
-
{:name => "label", :attr_type => :string, :header => "Label"},
|
68
|
-
{:name => "default_value", :attr_type => :string}
|
69
|
-
]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
def load_persistent_fields
|
75
|
-
# NetzkeFieldList.read_list(global_id) if persistent_config_enabled?
|
76
|
-
end
|
77
|
-
|
78
|
-
def load_model_level_attrs
|
79
|
-
# NetzkeModelAttrList.read_list(data_class.name) if persistent_config_enabled? && data_class
|
80
|
-
end
|
81
|
-
|
82
|
-
# This is where we expand our basic field config with all the defaults
|
83
|
-
def normalize_field(field)
|
84
|
-
# field can only be a string, a symbol, or a hash
|
85
|
-
if field.is_a?(Hash)
|
86
|
-
field = field.dup # we don't want to modify original hash
|
87
|
-
return field if field[:no_binding] # stop here if no normalization is needed
|
88
|
-
field[:name] = field[:name].to_s if field[:name] # all names should be strings
|
89
|
-
else
|
90
|
-
field = {:name => field.to_s}
|
91
|
-
end
|
92
|
-
|
93
|
-
field_from_model = fields_from_model && fields_from_model[field[:name].to_sym]
|
94
|
-
|
95
|
-
field_from_model && field.merge!(field_from_model)
|
96
|
-
|
97
|
-
detect_association_with_method(field) # xtype for an association field
|
98
|
-
set_default_field_label(field)
|
99
|
-
set_default_field_xtype(field) if field[:xtype].nil?
|
100
|
-
set_default_read_only(field)
|
101
|
-
|
102
|
-
# temporal datetime setup, while we don't have real datetime field
|
103
|
-
if field[:attr_type] == :date
|
104
|
-
field[:format] ||= "Y-m-d"
|
105
|
-
end
|
106
|
-
|
107
|
-
# provide our special combobox with our id
|
108
|
-
field[:parent_id] = self.global_id if field[:xtype] == :netzkeremotecombo
|
109
|
-
|
110
|
-
field[:hidden] = field[:hide_label] = true if field[:hidden].nil? && primary_key_attr?(field)
|
111
|
-
|
112
|
-
# checkbox setup
|
113
|
-
field[:checked] = field[:value] if field[:attr_type] == :boolean
|
114
|
-
field[:input_value] = true if field[:attr_type] == :boolean
|
115
|
-
|
116
|
-
field
|
117
|
-
end
|
118
|
-
|
119
|
-
# Sets the proper xtype of an asociation field
|
120
|
-
def detect_association_with_method(c)
|
121
|
-
if c[:name].index('__')
|
122
|
-
assoc_name, method = c[:name].split('__').map(&:to_sym)
|
123
|
-
assoc_method_type = data_adapter.get_assoc_property_type(assoc_name, method)
|
124
|
-
if c[:nested_attribute]
|
125
|
-
c[:xtype] ||= xtype_for_attr_type(assoc_method_type)
|
126
|
-
else
|
127
|
-
c[:xtype] ||= assoc_method_type == :boolean ? xtype_for_attr_type(assoc_method_type) : xtype_for_association
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# RECURSIVELY extracts fields configuration from :items
|
133
|
-
def normalize_fields(items)
|
134
|
-
@fields_from_config ||= {}
|
135
|
-
items.map do |item|
|
136
|
-
# at this moment, item is a hash or a symbol
|
137
|
-
if is_field_config?(item)
|
138
|
-
item = normalize_field(item)
|
139
|
-
@fields_from_config[item[:name].to_sym] = item
|
140
|
-
item #.reject{ |k,v| k == :name } # do we really need to remove the :name key?
|
141
|
-
elsif item.is_a?(Hash)
|
142
|
-
item = item.dup # we don't want to modify original hash
|
143
|
-
item[:items].is_a?(Array) ? item.merge(:items => normalize_fields(item[:items])) : item
|
144
|
-
else
|
145
|
-
item
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def is_field_config?(item)
|
151
|
-
item.is_a?(String) || item.is_a?(Symbol) || item[:name] # && !is_component_config?(item)
|
152
|
-
end
|
153
|
-
|
154
|
-
# Deeply merges only those key/values at the top level that are already there
|
155
|
-
def deep_merge_existing_fields(dest, src)
|
156
|
-
dest.each_pair do |k,v|
|
157
|
-
v.deep_merge!(src[k] || {})
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def set_default_field_label(c)
|
162
|
-
# multiple spaces (in case of association attrs) get replaced with one
|
163
|
-
c[:field_label] ||= data_class ? data_class.human_attribute_name(c[:name]) : c[:name].humanize
|
164
|
-
c[:field_label].gsub!(/\s+/, " ")
|
165
|
-
end
|
166
|
-
|
167
|
-
def set_default_field_xtype(field)
|
168
|
-
field[:xtype] = xtype_for_attr_type(field[:attr_type]) unless xtype_for_attr_type(field[:attr_type]).nil?
|
169
|
-
end
|
170
|
-
|
171
|
-
def set_default_read_only(field)
|
172
|
-
enabled_if = !data_class || data_class.column_names.include?(field[:name])
|
173
|
-
enabled_if ||= data_class.instance_methods.map(&:to_s).include?("#{field[:name]}=")
|
174
|
-
enabled_if ||= record && record.respond_to?("#{field[:name]}=")
|
175
|
-
enabled_if ||= association_attr?(field[:name])
|
176
|
-
|
177
|
-
field[:read_only] = !enabled_if if field[:read_only].nil?
|
178
|
-
end
|
179
|
-
|
180
|
-
def attr_type_to_xtype_map
|
181
|
-
{
|
182
|
-
:integer => :numberfield,
|
183
|
-
:boolean => config[:multi_edit] ? :tricheckbox : :checkboxfield,
|
184
|
-
:date => :datefield,
|
185
|
-
:datetime => :xdatetime,
|
186
|
-
:text => :textarea,
|
187
|
-
:json => :jsonfield,
|
188
|
-
:string => :textfield
|
189
|
-
}
|
190
|
-
end
|
191
|
-
|
192
|
-
def xtype_for_attr_type(type)
|
193
|
-
attr_type_to_xtype_map[type] || :textfield
|
194
|
-
end
|
195
|
-
|
196
|
-
def xtype_for_association
|
197
|
-
:netzkeremotecombo
|
198
|
-
end
|
199
|
-
|
200
|
-
# Are we provided with a static field layout?
|
201
|
-
def static_layout?
|
202
|
-
!!config[:items]
|
203
|
-
end
|
204
|
-
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|