netzke-basepack-zh 0.7.6
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/.autotest +1 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.rdoc +445 -0
- data/LICENSE +1 -0
- data/README.md +94 -0
- data/Rakefile +44 -0
- data/TODO.rdoc +8 -0
- data/config/ci/before-travis.sh +28 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/javascripts/basepack.js +139 -0
- data/javascripts/xdatetime.js +196 -0
- data/lib/generators/netzke/basepack_generator.rb +10 -0
- data/lib/generators/netzke/templates/assets/ts-checkbox.gif +0 -0
- data/lib/generators/netzke/templates/create_netzke_field_lists.rb +18 -0
- data/lib/netzke-basepack.rb +26 -0
- data/lib/netzke/active_record.rb +20 -0
- data/lib/netzke/active_record/attributes.rb +256 -0
- data/lib/netzke/active_record/combobox_options.rb +16 -0
- data/lib/netzke/active_record/relation_extensions.rb +37 -0
- data/lib/netzke/basepack.rb +45 -0
- data/lib/netzke/basepack/accordion_panel.rb +39 -0
- data/lib/netzke/basepack/action_column.rb +68 -0
- data/lib/netzke/basepack/action_column/javascripts/action_column.js +61 -0
- data/lib/netzke/basepack/auth_app.rb +159 -0
- data/lib/netzke/basepack/basic_app.rb +7 -0
- data/lib/netzke/basepack/border_layout_panel.rb +53 -0
- data/lib/netzke/basepack/border_layout_panel/javascripts/border_layout_panel.js +40 -0
- data/lib/netzke/basepack/data_accessor.rb +53 -0
- data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +164 -0
- data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +279 -0
- data/lib/netzke/basepack/data_adapters/data_mapper_adapter.rb +264 -0
- data/lib/netzke/basepack/data_adapters/sequel_adapter.rb +260 -0
- data/lib/netzke/basepack/form_panel.rb +144 -0
- data/lib/netzke/basepack/form_panel/fields.rb +208 -0
- data/lib/netzke/basepack/form_panel/javascripts/comma_list_cbg.js +51 -0
- data/lib/netzke/basepack/form_panel/javascripts/form_panel.js +225 -0
- data/lib/netzke/basepack/form_panel/javascripts/misc.js +4 -0
- data/lib/netzke/basepack/form_panel/javascripts/n_radio_group.js +43 -0
- data/lib/netzke/basepack/form_panel/javascripts/readonly_mode.js +35 -0
- data/lib/netzke/basepack/form_panel/services.rb +142 -0
- data/lib/netzke/basepack/form_panel/stylesheets/readonly_mode.css +14 -0
- data/lib/netzke/basepack/grid_panel.rb +440 -0
- data/lib/netzke/basepack/grid_panel/columns.rb +394 -0
- data/lib/netzke/basepack/grid_panel/javascripts/advanced_search.js +27 -0
- data/lib/netzke/basepack/grid_panel/javascripts/check_column_fix.js +6 -0
- data/lib/netzke/basepack/grid_panel/javascripts/edit_in_form.js +51 -0
- data/lib/netzke/basepack/grid_panel/javascripts/event_handling.js +179 -0
- data/lib/netzke/basepack/grid_panel/javascripts/grid_panel.js +438 -0
- data/lib/netzke/basepack/grid_panel/javascripts/misc.js +4 -0
- data/lib/netzke/basepack/grid_panel/javascripts/rows-dd.js +281 -0
- data/lib/netzke/basepack/grid_panel/record_form_window.rb +41 -0
- data/lib/netzke/basepack/grid_panel/services.rb +235 -0
- data/lib/netzke/basepack/paging_form_panel.rb +72 -0
- data/lib/netzke/basepack/paging_form_panel/javascripts/paging_form_panel.js +76 -0
- data/lib/netzke/basepack/panel.rb +11 -0
- data/lib/netzke/basepack/query_builder.rb +107 -0
- data/lib/netzke/basepack/query_builder/javascripts/query_builder.js +153 -0
- data/lib/netzke/basepack/search_panel.rb +79 -0
- data/lib/netzke/basepack/search_panel/javascripts/condition_field.js +160 -0
- data/lib/netzke/basepack/search_panel/javascripts/search_panel.js +65 -0
- data/lib/netzke/basepack/search_window.rb +66 -0
- data/lib/netzke/basepack/simple_app.rb +104 -0
- data/lib/netzke/basepack/simple_app/javascripts/simple_app.js +64 -0
- data/lib/netzke/basepack/simple_app/javascripts/statusbar_ext.js +8 -0
- data/lib/netzke/basepack/tab_panel.rb +21 -0
- data/lib/netzke/basepack/tab_panel/javascripts/tab_panel.js +11 -0
- data/lib/netzke/basepack/version.rb +11 -0
- data/lib/netzke/basepack/window.rb +29 -0
- data/lib/netzke/basepack/window/javascripts/window.js +20 -0
- data/lib/netzke/basepack/wrap_lazy_loaded.rb +28 -0
- data/lib/netzke/basepack/wrapper.rb +28 -0
- data/lib/netzke/data_mapper.rb +18 -0
- data/lib/netzke/data_mapper/attributes.rb +273 -0
- data/lib/netzke/data_mapper/combobox_options.rb +11 -0
- data/lib/netzke/data_mapper/relation_extensions.rb +38 -0
- data/lib/netzke/sequel.rb +18 -0
- data/lib/netzke/sequel/attributes.rb +274 -0
- data/lib/netzke/sequel/combobox_options.rb +10 -0
- data/lib/netzke/sequel/relation_extensions.rb +40 -0
- data/lib/tasks/netzke_basepack_tasks.rake +4 -0
- data/locales/de.yml +79 -0
- data/locales/en.yml +79 -0
- data/netzke-basepack.gemspec +306 -0
- data/stylesheets/basepack.css +72 -0
- data/stylesheets/datetimefield.css +54 -0
- data/test/basepack_test_app/.gitignore +6 -0
- data/test/basepack_test_app/.rvmrc +1 -0
- data/test/basepack_test_app/Gemfile +59 -0
- data/test/basepack_test_app/Gemfile.lock +196 -0
- data/test/basepack_test_app/Guardfile +46 -0
- data/test/basepack_test_app/README +1 -0
- data/test/basepack_test_app/Rakefile +7 -0
- data/test/basepack_test_app/app/components/author_form.rb +32 -0
- data/test/basepack_test_app/app/components/author_grid.rb +3 -0
- data/test/basepack_test_app/app/components/book_form.rb +38 -0
- data/test/basepack_test_app/app/components/book_form_with_custom_fields.rb +21 -0
- data/test/basepack_test_app/app/components/book_form_with_defaults.rb +8 -0
- data/test/basepack_test_app/app/components/book_form_with_nested_attributes.rb +18 -0
- data/test/basepack_test_app/app/components/book_grid.rb +12 -0
- data/test/basepack_test_app/app/components/book_grid_filtering.rb +10 -0
- data/test/basepack_test_app/app/components/book_grid_loader.rb +24 -0
- data/test/basepack_test_app/app/components/book_grid_with_column_actions.rb +15 -0
- data/test/basepack_test_app/app/components/book_grid_with_custom_columns.rb +27 -0
- data/test/basepack_test_app/app/components/book_grid_with_default_values.rb +9 -0
- data/test/basepack_test_app/app/components/book_grid_with_extra_feedback.rb +8 -0
- data/test/basepack_test_app/app/components/book_grid_with_extra_filters.rb +14 -0
- data/test/basepack_test_app/app/components/book_grid_with_nested_attributes.rb +13 -0
- data/test/basepack_test_app/app/components/book_grid_with_overridden_columns.rb +15 -0
- data/test/basepack_test_app/app/components/book_grid_with_paging.rb +10 -0
- data/test/basepack_test_app/app/components/book_grid_with_persistence.rb +8 -0
- data/test/basepack_test_app/app/components/book_grid_with_scoped_authors.rb +8 -0
- data/test/basepack_test_app/app/components/book_grid_with_virtual_attributes.rb +21 -0
- data/test/basepack_test_app/app/components/book_paging_form_panel.rb +22 -0
- data/test/basepack_test_app/app/components/book_query_builder.rb +8 -0
- data/test/basepack_test_app/app/components/book_search_panel.rb +5 -0
- data/test/basepack_test_app/app/components/book_search_panel/javascripts/i18n_de.js +6 -0
- data/test/basepack_test_app/app/components/book_with_custom_primary_key_grid.rb +10 -0
- data/test/basepack_test_app/app/components/books_bound_to_author.rb +10 -0
- data/test/basepack_test_app/app/components/double_book_grid.rb +18 -0
- data/test/basepack_test_app/app/components/extras/book_presentation.rb +27 -0
- data/test/basepack_test_app/app/components/form_without_model.rb +21 -0
- data/test/basepack_test_app/app/components/generic_user_form.rb +12 -0
- data/test/basepack_test_app/app/components/lockable_book_form.rb +17 -0
- data/test/basepack_test_app/app/components/lockable_user_form.rb +7 -0
- data/test/basepack_test_app/app/components/paging_form_with_search.rb +40 -0
- data/test/basepack_test_app/app/components/simple_accordion.rb +11 -0
- data/test/basepack_test_app/app/components/simple_panel.rb +17 -0
- data/test/basepack_test_app/app/components/simple_tab_panel.rb +11 -0
- data/test/basepack_test_app/app/components/simple_window.rb +10 -0
- data/test/basepack_test_app/app/components/simple_wrapper.rb +7 -0
- data/test/basepack_test_app/app/components/some_accordion_panel.rb +22 -0
- data/test/basepack_test_app/app/components/some_auth_app.rb +32 -0
- data/test/basepack_test_app/app/components/some_border_layout.rb +28 -0
- data/test/basepack_test_app/app/components/some_simple_app.rb +35 -0
- data/test/basepack_test_app/app/components/some_tab_panel.rb +20 -0
- data/test/basepack_test_app/app/components/user_form.rb +25 -0
- data/test/basepack_test_app/app/components/user_form_with_default_fields.rb +8 -0
- data/test/basepack_test_app/app/components/user_grid.rb +8 -0
- data/test/basepack_test_app/app/components/user_grid_with_customized_form_fields.rb +18 -0
- data/test/basepack_test_app/app/components/window_component_loader.rb +27 -0
- data/test/basepack_test_app/app/controllers/application_controller.rb +9 -0
- data/test/basepack_test_app/app/controllers/components_controller.rb +10 -0
- data/test/basepack_test_app/app/controllers/welcome_controller.rb +9 -0
- data/test/basepack_test_app/app/helpers/application_helper.rb +8 -0
- data/test/basepack_test_app/app/helpers/embedded_components_helper.rb +2 -0
- data/test/basepack_test_app/app/models/address.rb +29 -0
- data/test/basepack_test_app/app/models/author.rb +38 -0
- data/test/basepack_test_app/app/models/book.rb +49 -0
- data/test/basepack_test_app/app/models/book_with_custom_primary_key.rb +26 -0
- data/test/basepack_test_app/app/models/role.rb +24 -0
- data/test/basepack_test_app/app/models/user.rb +29 -0
- data/test/basepack_test_app/app/presenters/forms/generic_user.rb +6 -0
- data/test/basepack_test_app/app/views/components/loadable_window.html.erb +9 -0
- data/test/basepack_test_app/app/views/components/simple_panel.html.erb +1 -0
- data/test/basepack_test_app/app/views/layouts/application.html.erb +12 -0
- data/test/basepack_test_app/app/views/layouts/components.html.erb +13 -0
- data/test/basepack_test_app/app/views/layouts/nested.html.erb +5 -0
- data/test/basepack_test_app/app/views/welcome/index.html.erb +10 -0
- data/test/basepack_test_app/config.ru +4 -0
- data/test/basepack_test_app/config/application.rb +57 -0
- data/test/basepack_test_app/config/boot.rb +13 -0
- data/test/basepack_test_app/config/cucumber.yml +8 -0
- data/test/basepack_test_app/config/database.yml.sample +41 -0
- data/test/basepack_test_app/config/database.yml.travis +15 -0
- data/test/basepack_test_app/config/environment.rb +6 -0
- data/test/basepack_test_app/config/environments/development.rb +22 -0
- data/test/basepack_test_app/config/environments/production.rb +49 -0
- data/test/basepack_test_app/config/environments/test.rb +35 -0
- data/test/basepack_test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/basepack_test_app/config/initializers/data_mapper_logging.rb +3 -0
- data/test/basepack_test_app/config/initializers/inflections.rb +10 -0
- data/test/basepack_test_app/config/initializers/mime_types.rb +5 -0
- data/test/basepack_test_app/config/initializers/netzke.rb +9 -0
- data/test/basepack_test_app/config/initializers/secret_token.rb +7 -0
- data/test/basepack_test_app/config/initializers/sequel.rb +26 -0
- data/test/basepack_test_app/config/initializers/session_store.rb +8 -0
- data/test/basepack_test_app/config/locales/de.yml +35 -0
- data/test/basepack_test_app/config/locales/es.yml +96 -0
- data/test/basepack_test_app/config/routes.rb +68 -0
- data/test/basepack_test_app/db/development_structure.sql +88 -0
- data/test/basepack_test_app/db/migrate/20100914104207_create_users.rb +15 -0
- data/test/basepack_test_app/db/migrate/20100914104236_create_roles.rb +13 -0
- data/test/basepack_test_app/db/migrate/20101026185816_create_authors.rb +14 -0
- data/test/basepack_test_app/db/migrate/20101026190021_create_books.rb +19 -0
- data/test/basepack_test_app/db/migrate/20110101143818_create_addresses.rb +17 -0
- data/test/basepack_test_app/db/migrate/20110213213050_create_netzke_component_states.rb +20 -0
- data/test/basepack_test_app/db/migrate/20110701070052_create_book_with_custom_primary_keys.rb +15 -0
- data/test/basepack_test_app/db/migrate/20110901114016_add_last_read_at_to_books.rb +9 -0
- data/test/basepack_test_app/db/migrate/20110909071740_add_published_on_to_books.rb +5 -0
- data/test/basepack_test_app/db/schema.rb +81 -0
- data/test/basepack_test_app/db/seeds.rb +44 -0
- data/test/basepack_test_app/features/accordion_panel.feature +12 -0
- data/test/basepack_test_app/features/components_in_view.feature +11 -0
- data/test/basepack_test_app/features/form_panel.feature +142 -0
- data/test/basepack_test_app/features/grid_panel.feature +277 -0
- data/test/basepack_test_app/features/grid_panel_filters.feature +73 -0
- data/test/basepack_test_app/features/grid_panel_with_custom_primary_key.feature +15 -0
- data/test/basepack_test_app/features/grid_sorting.feature +47 -0
- data/test/basepack_test_app/features/i18n.feature +18 -0
- data/test/basepack_test_app/features/nested_attributes.feature +26 -0
- data/test/basepack_test_app/features/paging_form_panel.feature +43 -0
- data/test/basepack_test_app/features/search_in_grid.feature +49 -0
- data/test/basepack_test_app/features/simple_app.feature +15 -0
- data/test/basepack_test_app/features/simple_panel.feature +11 -0
- data/test/basepack_test_app/features/step_definitions/accordion_steps.rb +5 -0
- data/test/basepack_test_app/features/step_definitions/ext_steps.rb +16 -0
- data/test/basepack_test_app/features/step_definitions/form_panel_steps.rb +46 -0
- data/test/basepack_test_app/features/step_definitions/generic_steps.rb +44 -0
- data/test/basepack_test_app/features/step_definitions/grid_panel_steps.rb +186 -0
- data/test/basepack_test_app/features/step_definitions/pickle_steps.rb +100 -0
- data/test/basepack_test_app/features/step_definitions/web_steps.rb +219 -0
- data/test/basepack_test_app/features/support/env.rb +81 -0
- data/test/basepack_test_app/features/support/paths.rb +65 -0
- data/test/basepack_test_app/features/support/pickle.rb +24 -0
- data/test/basepack_test_app/features/support/selectors.rb +39 -0
- data/test/basepack_test_app/features/tab_panel.feature +12 -0
- data/test/basepack_test_app/features/validations_in_grid.feature +13 -0
- data/test/basepack_test_app/features/virtual_attributes.feature +16 -0
- data/test/basepack_test_app/features/window.feature +11 -0
- data/test/basepack_test_app/lib/tasks/.gitkeep +0 -0
- data/test/basepack_test_app/lib/tasks/cucumber.rake +71 -0
- data/test/basepack_test_app/lib/tasks/travis.rake +7 -0
- data/test/basepack_test_app/public/404.html +26 -0
- data/test/basepack_test_app/public/422.html +26 -0
- data/test/basepack_test_app/public/500.html +26 -0
- data/test/basepack_test_app/public/favicon.ico +0 -0
- data/test/basepack_test_app/public/images/header-deco.gif +0 -0
- data/test/basepack_test_app/public/images/rails.png +0 -0
- data/test/basepack_test_app/public/javascripts/application.js +2 -0
- data/test/basepack_test_app/public/javascripts/controls.js +965 -0
- data/test/basepack_test_app/public/javascripts/dragdrop.js +974 -0
- data/test/basepack_test_app/public/javascripts/effects.js +1123 -0
- data/test/basepack_test_app/public/javascripts/prototype.js +6001 -0
- data/test/basepack_test_app/public/javascripts/rails.js +175 -0
- data/test/basepack_test_app/public/robots.txt +5 -0
- data/test/basepack_test_app/public/stylesheets/.gitkeep +0 -0
- data/test/basepack_test_app/script/cucumber +10 -0
- data/test/basepack_test_app/script/rails +6 -0
- data/test/basepack_test_app/spec/components/form_panel_spec.rb +53 -0
- data/test/basepack_test_app/spec/components/grid_panel_spec.rb +10 -0
- data/test/basepack_test_app/spec/data_adapter/adapter_spec.rb +68 -0
- data/test/basepack_test_app/spec/data_adapter/attributes_spec.rb +56 -0
- data/test/basepack_test_app/spec/data_adapter/relation_extensions_spec.rb +125 -0
- data/test/basepack_test_app/spec/factories.rb +28 -0
- data/test/basepack_test_app/spec/spec_helper.rb +39 -0
- data/test/basepack_test_app/test/performance/browsing_test.rb +9 -0
- data/test/basepack_test_app/test/test_helper.rb +13 -0
- data/test/basepack_test_app/vendor/plugins/.gitkeep +0 -0
- data/test/console_with_fixtures.rb +4 -0
- data/test/fixtures/books.yml +11 -0
- data/test/fixtures/categories.yml +7 -0
- data/test/fixtures/cities.yml +21 -0
- data/test/fixtures/continents.yml +7 -0
- data/test/fixtures/countries.yml +9 -0
- data/test/fixtures/genres.yml +9 -0
- data/test/fixtures/roles.yml +8 -0
- data/test/fixtures/users.yml +11 -0
- data/test/schema.rb +10 -0
- data/test/test_helper.rb +21 -0
- data/test/unit/accordion_panel_test.rb +20 -0
- data/test/unit/active_record_basepack_test.rb +54 -0
- data/test/unit/fields_configuration_test.rb +18 -0
- data/test/unit/grid_panel_test.rb +52 -0
- data/test/unit/netzke_basepack_test.rb +4 -0
- data/test/unit/tab_panel_test.rb +21 -0
- data/uninstall.rb +1 -0
- metadata +332 -0
|
@@ -0,0 +1,260 @@
|
|
|
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
|
|
@@ -0,0 +1,144 @@
|
|
|
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
|
|
@@ -0,0 +1,208 @@
|
|
|
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
|