releaf-core 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +24 -0
- data/app/assets/fonts/releaf/RobotoRegular_normal_400.ttf +0 -0
- data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff +0 -0
- data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff2 +0 -0
- data/app/assets/images/releaf/icons/apple-touch-icon-114x114-precomposed.png +0 -0
- data/app/assets/images/releaf/icons/apple-touch-icon-152x152-precomposed.png +0 -0
- data/app/assets/images/releaf/icons/apple-touch-icon-72x72-precomposed.png +0 -0
- data/app/assets/images/releaf/icons/favicon.ico +0 -0
- data/app/assets/images/releaf/icons/favicon.png +0 -0
- data/app/assets/images/releaf/icons/msapplication-tile-144x144.png +0 -0
- data/app/assets/images/releaf/logo-login.png +0 -0
- data/app/assets/images/releaf/logo.png +0 -0
- data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/hidpi/mediaembed.png +0 -0
- data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/mediaembed.png +0 -0
- data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/en.js +12 -0
- data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/es.js +12 -0
- data/app/assets/javascripts/ckeditor/plugins/mediaembed/plugin.js +63 -0
- data/app/assets/javascripts/releaf/3rd_party/jquery-ui-timepicker-addon.js +1882 -0
- data/app/assets/javascripts/releaf/3rd_party/jquery.magnific-popup.min.js +4 -0
- data/app/assets/javascripts/releaf/application.js +13 -0
- data/app/assets/javascripts/releaf/include/ajax.js +66 -0
- data/app/assets/javascripts/releaf/include/ajaxbox.js +179 -0
- data/app/assets/javascripts/releaf/include/dialogs.js +13 -0
- data/app/assets/javascripts/releaf/include/field.type_associated_set.js +32 -0
- data/app/assets/javascripts/releaf/include/field.type_date_or_datetime_or_time.js +73 -0
- data/app/assets/javascripts/releaf/include/field.type_richtext.js +188 -0
- data/app/assets/javascripts/releaf/include/loader.js +45 -0
- data/app/assets/javascripts/releaf/include/localization.js +213 -0
- data/app/assets/javascripts/releaf/include/nested_fields.js +295 -0
- data/app/assets/javascripts/releaf/include/notifications.js +267 -0
- data/app/assets/javascripts/releaf/include/pagination.js +19 -0
- data/app/assets/javascripts/releaf/include/profile_settings.js +28 -0
- data/app/assets/javascripts/releaf/include/remote_validator.js +437 -0
- data/app/assets/javascripts/releaf/include/search.js +140 -0
- data/app/assets/javascripts/releaf/include/sidebar.js +149 -0
- data/app/assets/javascripts/releaf/include/sortable.js +69 -0
- data/app/assets/javascripts/releaf/include/toolbox.js +221 -0
- data/app/assets/javascripts/releaf/include/url_builder.js +193 -0
- data/app/assets/stylesheets/releaf/application.scss +9 -0
- data/app/assets/stylesheets/releaf/environment/extras.scss +11 -0
- data/app/assets/stylesheets/releaf/environment/functions/units.scss +12 -0
- data/app/assets/stylesheets/releaf/environment/functions.scss +1 -0
- data/app/assets/stylesheets/releaf/environment/mixins/blocks.scss +133 -0
- data/app/assets/stylesheets/releaf/environment/mixins/elements.scss +64 -0
- data/app/assets/stylesheets/releaf/environment/mixins/text.scss +61 -0
- data/app/assets/stylesheets/releaf/environment/mixins.scss +3 -0
- data/app/assets/stylesheets/releaf/environment/variables/colors.scss +93 -0
- data/app/assets/stylesheets/releaf/environment/variables/dimensions.scss +0 -0
- data/app/assets/stylesheets/releaf/environment/variables/magnific-popup.scss +6 -0
- data/app/assets/stylesheets/releaf/environment/variables.scss +5 -0
- data/app/assets/stylesheets/releaf/environment.scss +4 -0
- data/app/assets/stylesheets/releaf/layout/base.scss +32 -0
- data/app/assets/stylesheets/releaf/layout/breadcrumbs.scss +47 -0
- data/app/assets/stylesheets/releaf/layout/buttons.scss +107 -0
- data/app/assets/stylesheets/releaf/layout/deprecated.scss +29 -0
- data/app/assets/stylesheets/releaf/layout/dialogs.scss +138 -0
- data/app/assets/stylesheets/releaf/layout/errors.scss +28 -0
- data/app/assets/stylesheets/releaf/layout/extras.scss +10 -0
- data/app/assets/stylesheets/releaf/layout/fields.scss +305 -0
- data/app/assets/stylesheets/releaf/layout/fonts.scss +16 -0
- data/app/assets/stylesheets/releaf/layout/footer.scss +80 -0
- data/app/assets/stylesheets/releaf/layout/forms.scss +23 -0
- data/app/assets/stylesheets/releaf/layout/header.scss +55 -0
- data/app/assets/stylesheets/releaf/layout/icons.scss +4 -0
- data/app/assets/stylesheets/releaf/layout/images.scss +4 -0
- data/app/assets/stylesheets/releaf/layout/links.scss +7 -0
- data/app/assets/stylesheets/releaf/layout/localization.scss +79 -0
- data/app/assets/stylesheets/releaf/layout/main.scss +43 -0
- data/app/assets/stylesheets/releaf/layout/notifications.scss +67 -0
- data/app/assets/stylesheets/releaf/layout/pagination.scss +18 -0
- data/app/assets/stylesheets/releaf/layout/search.scss +70 -0
- data/app/assets/stylesheets/releaf/layout/sections.scss +138 -0
- data/app/assets/stylesheets/releaf/layout/sidebar.scss +306 -0
- data/app/assets/stylesheets/releaf/layout/tables.scss +99 -0
- data/app/assets/stylesheets/releaf/layout/text.scss +31 -0
- data/app/assets/stylesheets/releaf/layout/toolboxes.scss +69 -0
- data/app/assets/stylesheets/releaf/layout.scss +35 -0
- data/app/assets/stylesheets/releaf/vendor/magnific-popup/main.scss +596 -0
- data/app/assets/stylesheets/releaf/vendor/magnific-popup/settings.scss +45 -0
- data/app/builders/releaf/builders/association_reflector.rb +58 -0
- data/app/builders/releaf/builders/base.rb +80 -0
- data/app/builders/releaf/builders/collection.rb +8 -0
- data/app/builders/releaf/builders/confirm_destroy_dialog_builder.rb +25 -0
- data/app/builders/releaf/builders/confirm_dialog_builder.rb +54 -0
- data/app/builders/releaf/builders/edit_builder.rb +66 -0
- data/app/builders/releaf/builders/form_builder.rb +594 -0
- data/app/builders/releaf/builders/index_builder.rb +118 -0
- data/app/builders/releaf/builders/orderer.rb +5 -0
- data/app/builders/releaf/builders/page/header_builder.rb +70 -0
- data/app/builders/releaf/builders/page/layout_builder.rb +155 -0
- data/app/builders/releaf/builders/page/menu_builder.rb +140 -0
- data/app/builders/releaf/builders/pagination_builder.rb +107 -0
- data/app/builders/releaf/builders/refused_destroy_dialog_builder.rb +68 -0
- data/app/builders/releaf/builders/resource.rb +9 -0
- data/app/builders/releaf/builders/resource_dialog.rb +8 -0
- data/app/builders/releaf/builders/resource_view.rb +54 -0
- data/app/builders/releaf/builders/show_builder.rb +3 -0
- data/app/builders/releaf/builders/table_builder.rb +280 -0
- data/app/builders/releaf/builders/tags/releaf_associated_set_field.rb +40 -0
- data/app/builders/releaf/builders/template.rb +8 -0
- data/app/builders/releaf/builders/toolbox.rb +23 -0
- data/app/builders/releaf/builders/toolbox_builder.rb +27 -0
- data/app/builders/releaf/builders/view.rb +132 -0
- data/app/builders/releaf/builders.rb +38 -0
- data/app/builders/releaf/core/settings/form_builder.rb +21 -0
- data/app/builders/releaf/core/settings/table_builder.rb +11 -0
- data/app/controllers/concerns/releaf/breadcrumbs.rb +42 -0
- data/app/controllers/concerns/releaf/richtext_attachments.rb +20 -0
- data/app/controllers/releaf/base_controller.rb +458 -0
- data/app/controllers/releaf/core/errors_controller.rb +5 -0
- data/app/controllers/releaf/core/settings_controller.rb +50 -0
- data/app/helpers/releaf/application_helper.rb +53 -0
- data/app/helpers/releaf/button_helper.rb +50 -0
- data/app/helpers/releaf/javascript_helper.rb +75 -0
- data/app/lib/releaf/core/assets_resolver.rb +58 -0
- data/app/lib/releaf/core/default_searchable_fields.rb +43 -0
- data/app/lib/releaf/core/error_formatter.rb +103 -0
- data/app/lib/releaf/core/item_orderer.rb +102 -0
- data/app/lib/releaf/core/resource_base.rb +66 -0
- data/app/lib/releaf/core/resource_fields.rb +6 -0
- data/app/lib/releaf/core/resource_params.rb +47 -0
- data/app/lib/releaf/core/resource_table_fields.rb +10 -0
- data/app/lib/releaf/core/resource_utilities.rb +36 -0
- data/app/lib/releaf/core/responders/access_denied_responder.rb +9 -0
- data/app/lib/releaf/core/responders/after_save_responder.rb +28 -0
- data/app/lib/releaf/core/responders/confirm_destroy_responder.rb +13 -0
- data/app/lib/releaf/core/responders/destroy_responder.rb +10 -0
- data/app/lib/releaf/core/responders/error_responder.rb +9 -0
- data/app/lib/releaf/core/responders/feature_disabled_responder.rb +9 -0
- data/app/lib/releaf/core/responders/page_not_found_responder.rb +9 -0
- data/app/lib/releaf/core/responders.rb +31 -0
- data/app/lib/releaf/core/search.rb +147 -0
- data/app/lib/releaf/core/template_field_type_mapper.rb +127 -0
- data/app/models/releaf/richtext_attachment.rb +6 -0
- data/app/models/releaf/settings.rb +27 -0
- data/app/views/layouts/releaf/admin.html.erb +1 -0
- data/app/views/releaf/base/confirm_destroy.ruby +1 -0
- data/app/views/releaf/base/create_releaf_richtext_attachment.haml +1 -0
- data/app/views/releaf/base/edit.ruby +1 -0
- data/app/views/releaf/base/index.ruby +1 -0
- data/app/views/releaf/base/new.ruby +1 -0
- data/app/views/releaf/base/refused_destroy.ruby +1 -0
- data/app/views/releaf/base/show.ruby +1 -0
- data/app/views/releaf/base/toolbox.ruby +1 -0
- data/app/views/releaf/error_pages/_error.html.haml +10 -0
- data/app/views/releaf/error_pages/access_denied.html.haml +1 -0
- data/app/views/releaf/error_pages/feature_disabled.html.haml +1 -0
- data/app/views/releaf/error_pages/page_not_found.html.haml +2 -0
- data/lib/generators/dummy/install_generator.rb +18 -0
- data/lib/generators/dummy/templates/builders/admin/books/form_builder.rb +13 -0
- data/lib/generators/dummy/templates/builders/admin/books/index_builder.rb +30 -0
- data/lib/generators/dummy/templates/builders/admin/books/table_builder.rb +7 -0
- data/lib/generators/dummy/templates/builders/admin/nodes/form_builder.rb +7 -0
- data/lib/generators/dummy/templates/config/routes.rb +19 -0
- data/lib/generators/dummy/templates/controllers/admin/authors_controller.rb +12 -0
- data/lib/generators/dummy/templates/controllers/admin/books_controller.rb +17 -0
- data/lib/generators/dummy/templates/controllers/admin/chapters_controller.rb +3 -0
- data/lib/generators/dummy/templates/controllers/admin/publishers_controller.rb +3 -0
- data/lib/generators/dummy/templates/controllers/application_controller.rb +39 -0
- data/lib/generators/dummy/templates/controllers/concerns/.keep +0 -0
- data/lib/generators/dummy/templates/controllers/concerns/node_controller.rb +37 -0
- data/lib/generators/dummy/templates/controllers/contacts_controller.rb +3 -0
- data/lib/generators/dummy/templates/controllers/home_pages_controller.rb +3 -0
- data/lib/generators/dummy/templates/controllers/text_pages_controller.rb +3 -0
- data/lib/generators/dummy/templates/initializers/releaf.rb +35 -0
- data/lib/generators/dummy/templates/migrations/create_authors.rb +14 -0
- data/lib/generators/dummy/templates/migrations/create_banners.rb +11 -0
- data/lib/generators/dummy/templates/migrations/create_book_sequels.rb +14 -0
- data/lib/generators/dummy/templates/migrations/create_books.rb +27 -0
- data/lib/generators/dummy/templates/migrations/create_bundles.rb +7 -0
- data/lib/generators/dummy/templates/migrations/create_chapters.rb +13 -0
- data/lib/generators/dummy/templates/migrations/create_home_pages.rb +9 -0
- data/lib/generators/dummy/templates/migrations/create_node_extra_fields.rb +5 -0
- data/lib/generators/dummy/templates/migrations/create_publishers.rb +8 -0
- data/lib/generators/dummy/templates/migrations/create_text_pages.rb +9 -0
- data/lib/generators/dummy/templates/models/author.rb +10 -0
- data/lib/generators/dummy/templates/models/banner.rb +5 -0
- data/lib/generators/dummy/templates/models/book.rb +19 -0
- data/lib/generators/dummy/templates/models/book_sequel.rb +4 -0
- data/lib/generators/dummy/templates/models/bundle.rb +17 -0
- data/lib/generators/dummy/templates/models/chapter.rb +7 -0
- data/lib/generators/dummy/templates/models/home_page.rb +5 -0
- data/lib/generators/dummy/templates/models/node.rb +10 -0
- data/lib/generators/dummy/templates/models/publisher.rb +9 -0
- data/lib/generators/dummy/templates/models/text_page.rb +5 -0
- data/lib/generators/dummy/templates/views/contacts/show.html.haml +1 -0
- data/lib/generators/dummy/templates/views/home_pages/show.haml +1 -0
- data/lib/generators/dummy/templates/views/layouts/application.html.haml +22 -0
- data/lib/generators/dummy/templates/views/text_pages/show.haml +1 -0
- data/lib/generators/releaf/install_generator.rb +93 -0
- data/lib/generators/releaf/templates/initializers/haml.rb +1 -0
- data/lib/generators/releaf/templates/initializers/releaf.rb +30 -0
- data/lib/generators/releaf/templates/migrations/create_releaf_nodes.rb +28 -0
- data/lib/generators/releaf/templates/migrations/create_releaf_permissions.rb +12 -0
- data/lib/generators/releaf/templates/migrations/create_releaf_richtext_attachments.rb +12 -0
- data/lib/generators/releaf/templates/migrations/create_releaf_roles.rb +9 -0
- data/lib/generators/releaf/templates/migrations/create_releaf_settings.rb +17 -0
- data/lib/generators/releaf/templates/migrations/create_releaf_translations.rb +21 -0
- data/lib/generators/releaf/templates/migrations/create_releaf_users.rb +52 -0
- data/lib/generators/releaf/templates/models/node.rb +3 -0
- data/lib/generators/releaf/templates/seeds/seeds.rb +54 -0
- data/lib/releaf/core/application.rb +17 -0
- data/lib/releaf/core/builders_autoload.rb +27 -0
- data/lib/releaf/core/component.rb +9 -0
- data/lib/releaf/core/configuration.rb +101 -0
- data/lib/releaf/core/engine.rb +35 -0
- data/lib/releaf/core/exceptions.rb +38 -0
- data/lib/releaf/core/route_mapper.rb +59 -0
- data/lib/releaf/core/settings_ui_component.rb +7 -0
- data/lib/releaf/core/validation_error_codes.rb +36 -0
- data/lib/releaf/version.rb +3 -0
- data/lib/releaf-core.rb +14 -0
- data/lib/tasks/releaf_tasks.rake +4 -0
- data/releaf-core.gemspec +35 -0
- data/spec/builders/builders/association_reflector_spec.rb +138 -0
- data/spec/builders/builders/base_spec.rb +276 -0
- data/spec/builders/builders/collection_spec.rb +18 -0
- data/spec/builders/builders/confirm_destroy_dialog_builder_spec.rb +71 -0
- data/spec/builders/builders/confirm_dialog_builder_spec.rb +105 -0
- data/spec/builders/builders/edit_builder_spec.rb +215 -0
- data/spec/builders/builders/form_builder_spec.rb +562 -0
- data/spec/builders/builders/index_builder_spec.rb +345 -0
- data/spec/builders/builders/orderer_spec.rb +22 -0
- data/spec/builders/builders/page/header_builder_spec.rb +143 -0
- data/spec/builders/builders/page/layout_builder_spec.rb +73 -0
- data/spec/builders/builders/page/menu_builder_spec.rb +160 -0
- data/spec/builders/builders/pagination_builder_spec.rb +330 -0
- data/spec/builders/builders/resource_dialog_spec.rb +21 -0
- data/spec/builders/builders/resource_view_spec.rb +158 -0
- data/spec/builders/builders/show_builder_spec.rb +7 -0
- data/spec/builders/builders/table_builder_spec.rb +638 -0
- data/spec/builders/builders/template_spec.rb +12 -0
- data/spec/builders/builders/toolbox_builder_spec.rb +67 -0
- data/spec/builders/builders/toolbox_spec.rb +48 -0
- data/spec/builders/builders/view_spec.rb +281 -0
- data/spec/builders/builders_spec.rb +134 -0
- data/spec/builders/core/settings/form_builder_spec.rb +69 -0
- data/spec/builders/core/settings/table_builder_spec.rb +21 -0
- data/spec/controllers/concerns/releaf/richtext_attachments_spec.rb +51 -0
- data/spec/controllers/releaf/base_controller_spec.rb +447 -0
- data/spec/controllers/releaf/core/settings_controller_spec.rb +31 -0
- data/spec/features/ajaxbox_spec.rb +111 -0
- data/spec/features/authorization_spec.rb +50 -0
- data/spec/features/dragonfly_integration_spec.rb +24 -0
- data/spec/features/edit_actions_spec.rb +142 -0
- data/spec/features/errors_spec.rb +29 -0
- data/spec/features/index_actions_spec.rb +85 -0
- data/spec/features/index_table_spec.rb +32 -0
- data/spec/features/menu_spec.rb +71 -0
- data/spec/features/richtext_attachments_spec.rb +64 -0
- data/spec/features/richtext_embed_spec.rb +29 -0
- data/spec/features/richtext_spec.rb +19 -0
- data/spec/features/search_spec.rb +825 -0
- data/spec/features/settings_spec.rb +38 -0
- data/spec/features/title_spec.rb +13 -0
- data/spec/fixtures/common_fields.yml +17 -0
- data/spec/fixtures/cs.png +0 -0
- data/spec/fixtures/time.formats.xlsx +0 -0
- data/spec/fixtures/unicorn.jpg +0 -0
- data/spec/helpers/application_helper_spec.rb +75 -0
- data/spec/helpers/button_helper_spec.rb +146 -0
- data/spec/lib/releaf/core/application_spec.rb +42 -0
- data/spec/lib/releaf/core/assets_resolver_spec.rb +113 -0
- data/spec/lib/releaf/core/configuration_spec.rb +230 -0
- data/spec/lib/releaf/core/default_searchable_fields_spec.rb +161 -0
- data/spec/lib/releaf/core/error_formatter_spec.rb +242 -0
- data/spec/lib/releaf/core/item_orderer_spec.rb +142 -0
- data/spec/lib/releaf/core/resource_base_spec.rb +174 -0
- data/spec/lib/releaf/core/resource_fields_spec.rb +12 -0
- data/spec/lib/releaf/core/resource_params_spec.rb +117 -0
- data/spec/lib/releaf/core/resource_table_fields_spec.rb +18 -0
- data/spec/lib/releaf/core/resource_utilities_spec.rb +87 -0
- data/spec/lib/releaf/core/responders/access_denied_responder_spec.rb +12 -0
- data/spec/lib/releaf/core/responders/after_save_responder_spec.rb +102 -0
- data/spec/lib/releaf/core/responders/confirm_destroy_responder_spec.rb +26 -0
- data/spec/lib/releaf/core/responders/destroy_responder_spec.rb +30 -0
- data/spec/lib/releaf/core/responders/error_responder_spec.rb +26 -0
- data/spec/lib/releaf/core/responders/feature_disabled_responder_spec.rb +12 -0
- data/spec/lib/releaf/core/responders/page_not_found_responder_spec.rb +12 -0
- data/spec/lib/releaf/core/responders_spec.rb +60 -0
- data/spec/lib/releaf/core/template_field_type_mapper_spec.rb +311 -0
- data/spec/lib/validation_error_codes_spec.rb +56 -0
- data/spec/misc/factories_spec.rb +43 -0
- data/spec/models/settings_spec.rb +58 -0
- data/spec/routing/route_mapper_spec.rb +185 -0
- data/spec/rspec_helpers/test_helpers_spec.rb +20 -0
- metadata +657 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// Settings //
|
3
|
+
////////////////////////
|
4
|
+
|
5
|
+
// overlay
|
6
|
+
$mfp-overlay-color: #0b0b0b !default; // Color of overlay screen
|
7
|
+
$mfp-overlay-opacity: 0.8 !default; // Opacity of overlay screen
|
8
|
+
$mfp-shadow: 0 0 8px rgba(0, 0, 0, 0.6) !default; // Shadow on image or iframe
|
9
|
+
|
10
|
+
// spacing
|
11
|
+
$mfp-popup-padding-left: 8px!default ; // Padding from left and from right side
|
12
|
+
$mfp-popup-padding-left-mobile: 6px !default; // Same as above, but is applied when width of window is less than 800px
|
13
|
+
|
14
|
+
$mfp-z-index-base: 1040 !default; // Base z-index of popup
|
15
|
+
|
16
|
+
// controls
|
17
|
+
$mfp-include-arrows: true !default; // Include styles for nav arrows
|
18
|
+
$mfp-controls-opacity: 0.65 !default; // Opacity of controls
|
19
|
+
$mfp-controls-color: #FFF !default; // Color of controls
|
20
|
+
$mfp-controls-border-color: #3F3F3F !default; // Border color of controls
|
21
|
+
$mfp-inner-close-icon-color: #333 !default; // Color of close button when inside
|
22
|
+
$mfp-controls-text-color: #CCC !default; // Color of preloader and "1 of X" indicator
|
23
|
+
$mfp-controls-text-color-hover: #FFF !default; // Hover color of preloader and "1 of X" indicator
|
24
|
+
$mfp-IE7support: true !default; // Very basic IE7 support
|
25
|
+
|
26
|
+
// Iframe-type options
|
27
|
+
$mfp-include-iframe-type: true !default; // Enable Iframe-type popups
|
28
|
+
$mfp-iframe-padding-top: 40px !default; // Iframe padding top
|
29
|
+
$mfp-iframe-background: #000 !default; // Background color of iframes
|
30
|
+
$mfp-iframe-max-width: 900px !default; // Maximum width of iframes
|
31
|
+
$mfp-iframe-ratio: 9/16 !default; // Ratio of iframe (9/16 = widescreen, 3/4 = standard, etc.)
|
32
|
+
|
33
|
+
// Image-type options
|
34
|
+
$mfp-include-image-type: true !default; // Enable Image-type popups
|
35
|
+
$mfp-image-background: #444 !default;
|
36
|
+
$mfp-image-padding-top: 40px !default; // Image padding top
|
37
|
+
$mfp-image-padding-bottom: 40px !default; // Image padding bottom
|
38
|
+
$mfp-include-mobile-layout-for-image: true !default; // Removes paddings from top and bottom
|
39
|
+
|
40
|
+
// Image caption options
|
41
|
+
$mfp-caption-title-color: #F3F3F3 !default; // Caption title color
|
42
|
+
$mfp-caption-subtitle-color: #BDBDBD !default; // Caption subtitle color
|
43
|
+
|
44
|
+
// A11y
|
45
|
+
$mfp-use-visuallyhidden: false !default; // Hide content from browsers, but make it available for screen readers
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Releaf::Builders::AssociationReflector
|
2
|
+
delegate :macro, :name, :klass, to: :reflection
|
3
|
+
|
4
|
+
attr_accessor :reflection, :fields, :sortable_column_name, :sortable_cache
|
5
|
+
|
6
|
+
def initialize(reflection, fields, sortable_column_name)
|
7
|
+
self.reflection = reflection
|
8
|
+
self.fields = fields
|
9
|
+
self.sortable_column_name = sortable_column_name.to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def sortable?
|
13
|
+
if @sortable.nil?
|
14
|
+
@sortable = (expected_order_clause == actual_order_clause)
|
15
|
+
end
|
16
|
+
|
17
|
+
@sortable
|
18
|
+
end
|
19
|
+
|
20
|
+
def destroyable?
|
21
|
+
if @destroyable.nil?
|
22
|
+
@destroyable = reflection
|
23
|
+
.active_record
|
24
|
+
.nested_attributes_options
|
25
|
+
.fetch(reflection.name, {})
|
26
|
+
.fetch(:allow_destroy, false)
|
27
|
+
end
|
28
|
+
|
29
|
+
@destroyable
|
30
|
+
end
|
31
|
+
|
32
|
+
def actual_order_clause
|
33
|
+
relation = reflection.klass.all
|
34
|
+
|
35
|
+
if reflection.scope
|
36
|
+
relation = relation.instance_exec(reflection.active_record, &reflection.scope)
|
37
|
+
end
|
38
|
+
|
39
|
+
extract_order_clause(relation)
|
40
|
+
end
|
41
|
+
|
42
|
+
def expected_order_clause
|
43
|
+
relation = reflection.klass.all.order(sortable_column_name)
|
44
|
+
extract_order_clause(relation)
|
45
|
+
end
|
46
|
+
|
47
|
+
def extract_order_clause(relation)
|
48
|
+
relation.order_values.map{|value| value_as_sql(value) }.join(", ")
|
49
|
+
end
|
50
|
+
|
51
|
+
def value_as_sql(value)
|
52
|
+
if value.respond_to?(:to_sql)
|
53
|
+
value.to_sql
|
54
|
+
else
|
55
|
+
value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Releaf::Builders::Base
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
delegate :controller, :controller_name, :url_for, :form_for,
|
5
|
+
:releaf_button, :params, :form_tag, :file_field_tag,
|
6
|
+
:request, :check_box_tag, :label_tag, :content_tag, :hidden_field_tag,
|
7
|
+
:render, :link_to, :flash, :truncate, :radio_button_tag,
|
8
|
+
:options_for_select, :action_name, :options_from_collection_for_select,
|
9
|
+
:select_tag, :text_field_tag,
|
10
|
+
:image_tag, :jquery_date_format, :cookies, :button_tag, :merge_attributes, to: :template
|
11
|
+
|
12
|
+
delegate :layout_settings, :access_control, :controller_scope_name,
|
13
|
+
:feature_available?, :index_url, to: :controller
|
14
|
+
|
15
|
+
alias_method :button, :releaf_button
|
16
|
+
|
17
|
+
def wrapper(content_or_attributes_with_block, attributes = {}, &block)
|
18
|
+
if block_given?
|
19
|
+
tag(:div, content_or_attributes_with_block, nil, nil, &block)
|
20
|
+
else
|
21
|
+
tag(:div, content_or_attributes_with_block, attributes)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def html_escape(value)
|
26
|
+
ERB::Util.html_escape(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def tag(*args, &block)
|
30
|
+
return content_tag(*args) unless block_given?
|
31
|
+
|
32
|
+
content_tag(*args) do
|
33
|
+
block_result = yield
|
34
|
+
if block_result.is_a? Array
|
35
|
+
safe_join do
|
36
|
+
block_result
|
37
|
+
end
|
38
|
+
else
|
39
|
+
block_result.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def template_variable(variable)
|
45
|
+
template.instance_variable_get("@#{variable}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def icon(name)
|
49
|
+
template.fa_icon(name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def safe_join(&block)
|
53
|
+
template.safe_join(yield)
|
54
|
+
end
|
55
|
+
|
56
|
+
def t(key, options = {})
|
57
|
+
options[:scope] = default_translation_scope unless options.key? :scope
|
58
|
+
I18n.t(key, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def translate_locale(locale)
|
62
|
+
t(locale, scope: "locales")
|
63
|
+
end
|
64
|
+
|
65
|
+
def locale_options(locales)
|
66
|
+
locales.collect do|locale|
|
67
|
+
[translate_locale(locale), locale]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def default_translation_scope
|
72
|
+
controller_scope_name
|
73
|
+
end
|
74
|
+
|
75
|
+
# calls `#to_text` on resource if resource supports it. Otherwise calls
|
76
|
+
# `#to_s` method
|
77
|
+
def resource_to_text(resource)
|
78
|
+
resource.send(resource.respond_to?(:to_text) ? :to_text : :to_s)
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Releaf::Builders::ConfirmDestroyDialogBuilder < Releaf::Builders::ConfirmDialogBuilder
|
2
|
+
def question_content
|
3
|
+
t("Do you want to delete the following object?")
|
4
|
+
end
|
5
|
+
|
6
|
+
def description_content
|
7
|
+
resource_to_text(resource)
|
8
|
+
end
|
9
|
+
|
10
|
+
def section_header_text
|
11
|
+
t("Confirm deletion")
|
12
|
+
end
|
13
|
+
|
14
|
+
def confirm_method
|
15
|
+
:delete
|
16
|
+
end
|
17
|
+
|
18
|
+
def icon_name
|
19
|
+
"trash-o"
|
20
|
+
end
|
21
|
+
|
22
|
+
def confirm_url
|
23
|
+
url_for( action: 'destroy', id: resource.id, index_url: index_url)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Releaf::Builders::ConfirmDialogBuilder
|
2
|
+
include Releaf::Builders::ResourceDialog
|
3
|
+
|
4
|
+
attr_accessor :form
|
5
|
+
|
6
|
+
def output
|
7
|
+
tag(:section, section_attributes) do
|
8
|
+
form_for(resource, confirm_form_options) do |form|
|
9
|
+
self.form = form
|
10
|
+
safe_join do
|
11
|
+
section_blocks
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def section_body
|
18
|
+
tag(:div, class: "body") do
|
19
|
+
section_body_blocks
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def section_body_blocks
|
24
|
+
[
|
25
|
+
icon(icon_name),
|
26
|
+
tag(:div, question_content, class: "question"),
|
27
|
+
tag(:div, description_content, class: "description")
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
def section_attributes
|
32
|
+
merge_attributes(super, class: ["confirm"])
|
33
|
+
end
|
34
|
+
|
35
|
+
def footer_primary_tools
|
36
|
+
[cancel_button, confirm_button]
|
37
|
+
end
|
38
|
+
|
39
|
+
def confirm_form_options
|
40
|
+
{builder: Releaf::Builders::FormBuilder, url: confirm_url, as: :resource, method: confirm_method}
|
41
|
+
end
|
42
|
+
|
43
|
+
def confirm_button
|
44
|
+
button(t("Yes"), "check", class: "danger", type: 'submit')
|
45
|
+
end
|
46
|
+
|
47
|
+
def cancel_url
|
48
|
+
index_url
|
49
|
+
end
|
50
|
+
|
51
|
+
def cancel_button
|
52
|
+
button(t("No"), "ban", class: "secondary", data: {type: 'cancel'}, href: index_url)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class Releaf::Builders::EditBuilder
|
2
|
+
include Releaf::Builders::ResourceView
|
3
|
+
|
4
|
+
attr_accessor :form
|
5
|
+
|
6
|
+
def section_content
|
7
|
+
form_for(resource, form_options) do |form|
|
8
|
+
self.form = form
|
9
|
+
safe_join do
|
10
|
+
[index_url_preserver] + section_blocks
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def index_url_preserver
|
16
|
+
hidden_field_tag 'index_url', params[:index_url] if params[:index_url].present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def section_body_blocks
|
20
|
+
[error_notices, form_fields]
|
21
|
+
end
|
22
|
+
|
23
|
+
def form_fields
|
24
|
+
form.releaf_fields(form.field_names.to_a)
|
25
|
+
end
|
26
|
+
|
27
|
+
def form_options
|
28
|
+
controller.form_options(action_name, resource, :resource)
|
29
|
+
end
|
30
|
+
|
31
|
+
def error_notices
|
32
|
+
return unless resource.errors.any?
|
33
|
+
tag(:div, class: "form-error-box") do
|
34
|
+
error_notices_header <<
|
35
|
+
tag(:ul) do
|
36
|
+
resource.errors.full_messages.collect do|message|
|
37
|
+
tag(:li, message, class: "error")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def error_notices_header
|
44
|
+
tag(:strong, "#{resource.errors.count} validation #{"error".pluralize(resource.errors.count)} occured:")
|
45
|
+
end
|
46
|
+
|
47
|
+
def footer_primary_tools
|
48
|
+
tools = []
|
49
|
+
tools << save_and_create_another_button if create_another_available?
|
50
|
+
tools << save_button
|
51
|
+
tools
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_another_available?
|
55
|
+
resource.present? && resource.new_record? && controller.feature_available?(:create_another)
|
56
|
+
end
|
57
|
+
|
58
|
+
def save_and_create_another_button
|
59
|
+
button(t("Save and create another"), "plus", name: "after_save", value: "create_another", class: "secondary", data: { type: 'ok', disable: true }, type: "submit")
|
60
|
+
end
|
61
|
+
|
62
|
+
def save_button
|
63
|
+
button(t("Save"), "check", class: "primary", data: { type: 'ok', disable: true }, type: "submit")
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,594 @@
|
|
1
|
+
class Releaf::Builders::FormBuilder < ActionView::Helpers::FormBuilder
|
2
|
+
include Releaf::Builders::Base
|
3
|
+
include Releaf::Tags::AssociatedSetField
|
4
|
+
include Releaf::Builders::Orderer
|
5
|
+
attr_accessor :template
|
6
|
+
|
7
|
+
def field_names
|
8
|
+
resource_fields.values
|
9
|
+
end
|
10
|
+
|
11
|
+
def resource_fields
|
12
|
+
Releaf::Core::ResourceFields.new(object.class)
|
13
|
+
end
|
14
|
+
|
15
|
+
def field_render_method_name(name)
|
16
|
+
parts = [name]
|
17
|
+
|
18
|
+
builder = self
|
19
|
+
until builder.options[:parent_builder].nil? do
|
20
|
+
parts << builder.options[:relation_name] if builder.options[:relation_name]
|
21
|
+
builder = builder.options[:parent_builder]
|
22
|
+
end
|
23
|
+
|
24
|
+
parts << "render"
|
25
|
+
parts.reverse.join("_")
|
26
|
+
end
|
27
|
+
|
28
|
+
def normalize_fields(fields)
|
29
|
+
fields.flatten.map do |item|
|
30
|
+
if item.is_a? Hash
|
31
|
+
item.each_pair.map do |(association, subfields)|
|
32
|
+
normalize_field(association, subfields)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
normalize_field(item, nil)
|
36
|
+
end
|
37
|
+
end.flatten
|
38
|
+
end
|
39
|
+
|
40
|
+
def normalize_field(field, subfields)
|
41
|
+
{
|
42
|
+
render_method: field_render_method_name(field),
|
43
|
+
field: field,
|
44
|
+
subfields: subfields
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def releaf_fields(*fields)
|
49
|
+
safe_join do
|
50
|
+
normalize_fields(fields).collect{|field_option| render_field_by_options(field_option) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def render_field_by_options(options)
|
55
|
+
if respond_to? options[:render_method]
|
56
|
+
send(options[:render_method])
|
57
|
+
else
|
58
|
+
reflection = reflect_on_association(options[:field])
|
59
|
+
|
60
|
+
if reflection
|
61
|
+
releaf_association_fields(reflection, options[:subfields])
|
62
|
+
else
|
63
|
+
releaf_field(options[:field])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def reflect_on_association(association_name)
|
69
|
+
object.class.reflect_on_association(association_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
def association_reflector(reflection, fields)
|
73
|
+
fields ||= resource_fields.association_attributes(reflection)
|
74
|
+
Releaf::Builders::AssociationReflector.new(reflection, fields, sortable_column_name)
|
75
|
+
end
|
76
|
+
|
77
|
+
def releaf_association_fields(reflection, fields)
|
78
|
+
reflector = association_reflector(reflection, fields)
|
79
|
+
|
80
|
+
case reflector.macro
|
81
|
+
when :has_many
|
82
|
+
releaf_has_many_association(reflector)
|
83
|
+
when :belongs_to
|
84
|
+
releaf_belongs_to_association(reflector)
|
85
|
+
when :has_one
|
86
|
+
releaf_has_one_association(reflector)
|
87
|
+
else
|
88
|
+
raise 'not implemented'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def releaf_belongs_to_association(reflector)
|
93
|
+
releaf_has_one_or_belongs_to_association(reflector)
|
94
|
+
end
|
95
|
+
|
96
|
+
def releaf_has_one_association(reflector)
|
97
|
+
object.send("build_#{reflector.name}") unless object.send(reflector.name).present?
|
98
|
+
releaf_has_one_or_belongs_to_association(reflector)
|
99
|
+
end
|
100
|
+
|
101
|
+
def releaf_has_one_or_belongs_to_association(reflector)
|
102
|
+
tag(:fieldset, class: "type-association", data: {name: reflector.name}) do
|
103
|
+
tag(:legend, translate_attribute(reflector.name)) <<
|
104
|
+
fields_for(reflector.name, object.send(reflector.name), relation_name: reflector.name, builder: self.class) do |builder|
|
105
|
+
builder.releaf_fields(reflector.fields)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def releaf_has_many_association(reflector)
|
111
|
+
item_template = releaf_has_many_association_fields(reflector, reflector.klass.new, '_template_', true)
|
112
|
+
|
113
|
+
tag(:section, class: "nested", data: {name: reflector.name, "releaf-template" => html_escape(item_template.to_str)}) do
|
114
|
+
[
|
115
|
+
releaf_has_many_association_header(reflector),
|
116
|
+
releaf_has_many_association_body(reflector),
|
117
|
+
releaf_has_many_association_footer(reflector)
|
118
|
+
]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def releaf_has_many_association_header(reflector)
|
123
|
+
tag(:header) do
|
124
|
+
tag(:h1, translate_attribute(reflector.name))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def releaf_has_many_association_body(reflector)
|
129
|
+
attributes = {
|
130
|
+
class: ["body", "list"]
|
131
|
+
}
|
132
|
+
attributes["data"] = {sortable: nil} if reflector.sortable?
|
133
|
+
|
134
|
+
tag(:div, attributes) do
|
135
|
+
association_collection(reflector).each_with_index.map do |association_object, index|
|
136
|
+
releaf_has_many_association_fields(reflector, association_object, index, reflector.destroyable?)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def releaf_has_many_association_footer(reflector)
|
142
|
+
tag(:footer){ field_type_add_nested }
|
143
|
+
end
|
144
|
+
|
145
|
+
def releaf_has_many_association_fields(reflector, association_object, association_index, destroyable)
|
146
|
+
tag(:fieldset, class: ["item", "type-association"], data: {name: reflector.name, index: association_index}) do
|
147
|
+
fields_for(reflector.name, association_object, relation_name: reflector.name,
|
148
|
+
child_index: association_index, builder: self.class) do |builder|
|
149
|
+
builder.releaf_has_many_association_field(reflector, destroyable)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def releaf_has_many_association_field(reflector, destroyable)
|
155
|
+
content = ActiveSupport::SafeBuffer.new
|
156
|
+
skippable_fields = []
|
157
|
+
|
158
|
+
if reflector.sortable?
|
159
|
+
skippable_fields << sortable_column_name
|
160
|
+
content << hidden_field(sortable_column_name.to_sym, class: "item-position")
|
161
|
+
content << tag(:div, " ".html_safe, class: "handle")
|
162
|
+
end
|
163
|
+
|
164
|
+
content << releaf_fields(reflector.fields - skippable_fields)
|
165
|
+
content << field_type_remove_nested if destroyable
|
166
|
+
|
167
|
+
content
|
168
|
+
end
|
169
|
+
|
170
|
+
def field_type_remove_nested
|
171
|
+
button_attributes = {title: t('Remove item'), class: "danger remove-nested-item"}
|
172
|
+
wrapper(class: "remove-item-box") do
|
173
|
+
button(nil, "trash-o", button_attributes) << hidden_field("_destroy", class: "destroy")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def field_type_add_nested
|
178
|
+
button(t('Add item'), "plus", class: "primary add-nested-item")
|
179
|
+
end
|
180
|
+
|
181
|
+
def field_type_method(name)
|
182
|
+
type = Releaf::Core::TemplateFieldTypeMapper.field_type_name(object, name)
|
183
|
+
localization = Releaf::Core::TemplateFieldTypeMapper.use_i18n?(object, name)
|
184
|
+
|
185
|
+
"releaf_#{type}_#{'i18n_' if localization}field"
|
186
|
+
end
|
187
|
+
|
188
|
+
def releaf_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
189
|
+
method_name = field_type_method(name)
|
190
|
+
send(method_name, name, input: input, label: label, field: field, options: options, &block)
|
191
|
+
end
|
192
|
+
|
193
|
+
def releaf_item_field_collection(name, options = {})
|
194
|
+
options[:collection] || object.class.reflect_on_association(relation_name(name)).try(:klass).try(:all)
|
195
|
+
end
|
196
|
+
|
197
|
+
def releaf_item_field_choices(name, options = {})
|
198
|
+
unless options.key? :select_options
|
199
|
+
options[:select_options] = releaf_item_field_collection(name, options)
|
200
|
+
.collect{|item| [resource_to_text(item), item.id]}
|
201
|
+
end
|
202
|
+
|
203
|
+
if options[:select_options].is_a? Array
|
204
|
+
choices = options_for_select(options[:select_options], object.send(name))
|
205
|
+
else
|
206
|
+
choices = options[:select_options]
|
207
|
+
end
|
208
|
+
|
209
|
+
choices
|
210
|
+
end
|
211
|
+
|
212
|
+
def relation_name(name)
|
213
|
+
name.to_s.sub(/_id$/, '').to_sym
|
214
|
+
end
|
215
|
+
|
216
|
+
def releaf_item_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
217
|
+
label = {translation_key: name.to_s.sub(/_id$/, '').to_s}.deep_merge(label)
|
218
|
+
attributes = input_attributes(name, {value: object.send(name)}.merge(input), options)
|
219
|
+
options = {field: {type: "item"}}.deep_merge(options)
|
220
|
+
|
221
|
+
|
222
|
+
# add empty value when validation exists, so user is forced to choose something
|
223
|
+
unless options.key? :include_blank
|
224
|
+
options[:include_blank] = true
|
225
|
+
object.class.validators_on(name).each do |validator|
|
226
|
+
next unless validator.is_a? ActiveModel::Validations::PresenceValidator
|
227
|
+
# if new record, or object is missing (was deleted)
|
228
|
+
options[:include_blank] = object.new_record? || object.send(relation_name(name)).blank?
|
229
|
+
break
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
choices = releaf_item_field_choices(name, options)
|
235
|
+
content = select(name, choices, options, attributes)
|
236
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
237
|
+
end
|
238
|
+
|
239
|
+
def releaf_image_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
240
|
+
name = name.to_s.sub(/_uid$/, '')
|
241
|
+
|
242
|
+
attributes = {
|
243
|
+
accept: 'image/png,image/jpeg,image/bmp,image/gif'
|
244
|
+
}.merge(input)
|
245
|
+
|
246
|
+
attributes = input_attributes(name, attributes, options)
|
247
|
+
|
248
|
+
options = {field: {type: "image"}}.deep_merge(options)
|
249
|
+
content = file_field(name, attributes)
|
250
|
+
if object.send(name).present?
|
251
|
+
content += tag(:div, class: "value-preview") do
|
252
|
+
inner_content = tag(:div, class: "image-wrap") do
|
253
|
+
thumbnail = image_tag(object.send(name).thumb('410x128>').url, alt: '')
|
254
|
+
hidden_field("retained_#{name}") +
|
255
|
+
link_to(thumbnail, object.send(name).url, target: :_blank, class: :ajaxbox, rel: :image)
|
256
|
+
end
|
257
|
+
inner_content << releaf_file_remove_button(name)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
262
|
+
end
|
263
|
+
|
264
|
+
def releaf_file_remove_button(name)
|
265
|
+
tag(:div, class: "remove") do
|
266
|
+
check_box("remove_#{name}") << label("remove_#{name}", t("Remove"))
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def releaf_file_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
271
|
+
name = name.to_s.sub(/_uid$/, '')
|
272
|
+
attributes = input_attributes(name, input, options)
|
273
|
+
options = {field: {type: "file"}}.deep_merge(options)
|
274
|
+
|
275
|
+
content = file_field(name, attributes)
|
276
|
+
if object.send(name).present?
|
277
|
+
content << hidden_field("retained_#{name}")
|
278
|
+
content << link_to(t("Download"), object.send(name).url, target: "_blank")
|
279
|
+
content << releaf_file_remove_button(name)
|
280
|
+
end
|
281
|
+
|
282
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
283
|
+
end
|
284
|
+
|
285
|
+
def releaf_boolean_field(name, input: {}, label: {}, field: {}, options: {})
|
286
|
+
attributes = input_attributes(name, input, options)
|
287
|
+
options = {field: {type: "boolean"}}.deep_merge(options)
|
288
|
+
|
289
|
+
wrapper(field_attributes(name, field, options)) do
|
290
|
+
wrapper(class: "value") do
|
291
|
+
check_box(name, attributes) << releaf_label(name, label, options.deep_merge(label: {minimal: true}))
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def date_or_time_fields(name, type, input: {}, label: {}, field: {}, options: {})
|
297
|
+
input = date_or_time_fields_input_attributes(name, type, input)
|
298
|
+
options = {field: {type: type.to_s}}.deep_merge(options)
|
299
|
+
releaf_text_field(name, input: input, label: label, field: field, options: options)
|
300
|
+
end
|
301
|
+
|
302
|
+
def date_or_time_fields_input_attributes(name, type, attributes)
|
303
|
+
value = object.send(name)
|
304
|
+
{
|
305
|
+
class: "text #{type}-picker",
|
306
|
+
data: {
|
307
|
+
"date-format" => date_format_for_jquery,
|
308
|
+
"time-format" => time_format_for_jquery
|
309
|
+
},
|
310
|
+
value: (format_date_or_time_value(value, type) if value)
|
311
|
+
}.merge(attributes)
|
312
|
+
end
|
313
|
+
|
314
|
+
def normalize_date_or_time_value(value, type)
|
315
|
+
case type
|
316
|
+
when :date
|
317
|
+
value.to_date
|
318
|
+
when :datetime
|
319
|
+
value.to_datetime
|
320
|
+
when :time
|
321
|
+
value.to_time
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def format_date_or_time_value(value, type)
|
326
|
+
default_format = date_or_time_default_format(type)
|
327
|
+
value = normalize_date_or_time_value(value, type)
|
328
|
+
|
329
|
+
if type == :time
|
330
|
+
value.strftime(default_format)
|
331
|
+
else
|
332
|
+
I18n.l(value, default: default_format)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def time_format_for_jquery
|
337
|
+
format = date_or_time_default_format(:time)
|
338
|
+
jquery_date_format(format)
|
339
|
+
end
|
340
|
+
|
341
|
+
def date_format_for_jquery
|
342
|
+
format = date_or_time_default_format(:date)
|
343
|
+
jquery_date_format(t("default", scope: "date.formats", default: format))
|
344
|
+
end
|
345
|
+
|
346
|
+
def date_or_time_default_format(type)
|
347
|
+
case type
|
348
|
+
when :date
|
349
|
+
"%Y-%m-%d"
|
350
|
+
when :datetime
|
351
|
+
"%Y-%m-%d %H:%M"
|
352
|
+
when :time
|
353
|
+
"%H:%M"
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def releaf_datetime_field(name, input: {}, label: {}, field: {}, options: {})
|
358
|
+
date_or_time_fields(name, :datetime, input: input, label: label, field: field, options: options)
|
359
|
+
end
|
360
|
+
|
361
|
+
def releaf_time_field(name, input: {}, label: {}, field: {}, options: {})
|
362
|
+
date_or_time_fields(name, :time, input: input, label: label, field: field, options: options)
|
363
|
+
end
|
364
|
+
|
365
|
+
def releaf_date_field(name, input: {}, label: {}, field: {}, options: {})
|
366
|
+
date_or_time_fields(name, :date, input: input, label: label, field: field, options: options)
|
367
|
+
end
|
368
|
+
|
369
|
+
def releaf_richtext_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
370
|
+
attributes = richtext_input_attributes(name)
|
371
|
+
.merge(value: object.send(name))
|
372
|
+
.merge(input)
|
373
|
+
attributes = input_attributes(name, attributes, options)
|
374
|
+
|
375
|
+
options = richtext_options(name, options)
|
376
|
+
content = text_area(name, attributes)
|
377
|
+
|
378
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
379
|
+
end
|
380
|
+
|
381
|
+
def releaf_textarea_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
382
|
+
attributes = {
|
383
|
+
rows: 5,
|
384
|
+
cols: 75,
|
385
|
+
value: object.send(name)
|
386
|
+
}.merge(input)
|
387
|
+
|
388
|
+
attributes = input_attributes(name, attributes, options)
|
389
|
+
|
390
|
+
options = {field: {type: "textarea"}}.deep_merge(options)
|
391
|
+
content = text_area(name, attributes)
|
392
|
+
|
393
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
394
|
+
end
|
395
|
+
|
396
|
+
def releaf_email_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
397
|
+
options = {field: {type: "email"}}.deep_merge(options)
|
398
|
+
input = {type: "email"}.deep_merge(input)
|
399
|
+
releaf_text_field(name, input: input, label: label, field: field, options: options, &block)
|
400
|
+
end
|
401
|
+
|
402
|
+
def releaf_link_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
403
|
+
options = {field: {type: "link"}}.deep_merge(options)
|
404
|
+
releaf_text_field(name, input: input, label: label, field: field, options: options, &block)
|
405
|
+
end
|
406
|
+
|
407
|
+
def releaf_password_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
408
|
+
attributes = input_attributes(name, {autocomplete: "off", class: "text"}.merge(input), options)
|
409
|
+
options = {field: {type: "password"}}.deep_merge(options)
|
410
|
+
content = password_field(name, attributes)
|
411
|
+
|
412
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
413
|
+
end
|
414
|
+
|
415
|
+
def releaf_number_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
416
|
+
attributes = input_attributes(name, {value: object.send(name), step: "any", class: "text" }.merge(input), options)
|
417
|
+
options = {field: {type: "number"}}.deep_merge(options)
|
418
|
+
content = number_field(name, attributes)
|
419
|
+
|
420
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
421
|
+
end
|
422
|
+
|
423
|
+
alias_method :releaf_integer_field, :releaf_number_field
|
424
|
+
alias_method :releaf_float_field, :releaf_number_field
|
425
|
+
alias_method :releaf_decimal_field, :releaf_number_field
|
426
|
+
|
427
|
+
def releaf_text_field(name, input: {}, label: {}, field: {}, options: {}, &block)
|
428
|
+
attributes = input_attributes(name, {value: object.send(name), class: "text"}.merge(input), options)
|
429
|
+
options = {field: {type: "text"}}.deep_merge(options)
|
430
|
+
content = text_field(name, attributes)
|
431
|
+
|
432
|
+
input_wrapper_with_label(name, content, label: label, field: field, options: options, &block)
|
433
|
+
end
|
434
|
+
|
435
|
+
def releaf_text_i18n_field(name, input: {}, label: {}, field: {}, options: {})
|
436
|
+
options = {field: {type: "text"}}.deep_merge(options)
|
437
|
+
input = {class: "text"}.deep_merge(input)
|
438
|
+
localized_field(name, :text_field, input: input, label: label, field: field, options: options)
|
439
|
+
end
|
440
|
+
|
441
|
+
def releaf_link_i18n_field(name, input: {}, label: {}, field: {}, options: {})
|
442
|
+
options = {field: {type: "link"}}.deep_merge(options)
|
443
|
+
input = {class: "text"}.deep_merge(input)
|
444
|
+
localized_field(name, :text_field, input: input, label: label, field: field, options: options)
|
445
|
+
end
|
446
|
+
|
447
|
+
def richtext_input_attributes(name)
|
448
|
+
{
|
449
|
+
rows: 5,
|
450
|
+
cols: 50,
|
451
|
+
class: "richtext",
|
452
|
+
data: {
|
453
|
+
"attachment-upload-url" => (controller.respond_to?(:releaf_richtext_attachment_upload_url) ? controller.releaf_richtext_attachment_upload_url : '')
|
454
|
+
},
|
455
|
+
}
|
456
|
+
end
|
457
|
+
|
458
|
+
def richtext_options(name, options)
|
459
|
+
{field: {type: "richtext"}, label: {translation_key: name.to_s.sub(/_html$/, '').to_s }}.deep_merge(options)
|
460
|
+
end
|
461
|
+
|
462
|
+
def releaf_richtext_i18n_field(name, input: {}, label: {}, field: {}, options: {})
|
463
|
+
input = richtext_input_attributes(name).merge(input)
|
464
|
+
options = richtext_options(name, options)
|
465
|
+
localized_field(name, :text_area, input: input, label: label, field: field, options: options)
|
466
|
+
end
|
467
|
+
|
468
|
+
def releaf_textarea_i18n_field(name, input: {}, label: {}, field: {}, options: {})
|
469
|
+
input = {
|
470
|
+
rows: 5,
|
471
|
+
cols: 75,
|
472
|
+
}.merge(input)
|
473
|
+
options = {field: {type: "textarea"}}.deep_merge(options)
|
474
|
+
localized_field(name, :text_area, input: input, label: label, field: field, options: options)
|
475
|
+
end
|
476
|
+
|
477
|
+
def default_locale
|
478
|
+
selected_locale = (cookies[:'releaf.i18n.locale'] || I18n.locale).to_sym
|
479
|
+
locales.include?(selected_locale) ? selected_locale : locales.first
|
480
|
+
end
|
481
|
+
|
482
|
+
def locales
|
483
|
+
object.class.globalize_locales
|
484
|
+
end
|
485
|
+
|
486
|
+
def localized_field(name, field_type, input: {}, label: {}, field: {}, options: {})
|
487
|
+
options = {i18n: true, label: {translation_key: name}}.deep_merge(options)
|
488
|
+
|
489
|
+
wrapper(field_attributes(name, field, options)) do
|
490
|
+
content = object.class.globalize_locales.collect do |locale|
|
491
|
+
localized_name = "#{name}_#{locale}"
|
492
|
+
html_class = ["localization"]
|
493
|
+
html_class << "active" if locale == default_locale
|
494
|
+
|
495
|
+
tag(:div, class: html_class, data: {locale: locale}) do
|
496
|
+
releaf_label(localized_name, label, options) <<
|
497
|
+
tag(:div, class: "value") do
|
498
|
+
attributes = input_attributes(name, {value: object.send(localized_name)}.merge(input), options)
|
499
|
+
send(field_type, localized_name, attributes)
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
content << localization_switch
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
def localization_switch
|
509
|
+
tag(:div, class: "localization-switch") do
|
510
|
+
button_tag(type: 'button', title: t('Switch locale'), class: "trigger") do
|
511
|
+
tag(:span, default_locale, class: "label") + tag(:i, nil, class: ["fa", "fa-chevron-down"])
|
512
|
+
end <<
|
513
|
+
tag(:menu, class: ["localization-menu-items"], type: 'toolbar') do
|
514
|
+
tag(:ul) do
|
515
|
+
object.class.globalize_locales.collect do |locale, i|
|
516
|
+
tag(:li) do
|
517
|
+
tag(:button, translate_locale(locale), type: "button", data: {locale: locale})
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
def input_wrapper_with_label(name, input_content, label: {}, field: {}, options: {})
|
526
|
+
field(name, field, options) do
|
527
|
+
input_content = safe_join{[input_content, yield.to_s]} if block_given?
|
528
|
+
releaf_label(name, label, options) << wrapper(input_content, class: "value")
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
def field(name, attributes, options, &block)
|
533
|
+
tag(:div, field_attributes(name, attributes, options), nil, nil, &block)
|
534
|
+
end
|
535
|
+
|
536
|
+
def field_attributes(name, attributes, options)
|
537
|
+
type = options.fetch(:field, {}).fetch(:type, nil)
|
538
|
+
|
539
|
+
classes = ["field", "type-#{type}"]
|
540
|
+
classes << "i18n" if options.key? :i18n
|
541
|
+
|
542
|
+
merge_attributes({class: classes, data: {name: name}}, attributes)
|
543
|
+
end
|
544
|
+
|
545
|
+
def label_attributes(name, attributes, options)
|
546
|
+
attributes
|
547
|
+
end
|
548
|
+
|
549
|
+
def input_attributes(name, attributes, options)
|
550
|
+
attributes
|
551
|
+
end
|
552
|
+
|
553
|
+
|
554
|
+
def releaf_label(name, attributes, options = {})
|
555
|
+
label_options = options.fetch(:label, {})
|
556
|
+
attributes = label_attributes(name, attributes, options)
|
557
|
+
text = label_text(name, label_options)
|
558
|
+
|
559
|
+
content = label(name, text, attributes)
|
560
|
+
|
561
|
+
if label_options.fetch(:minimal, false) == true
|
562
|
+
content
|
563
|
+
else
|
564
|
+
content += wrapper(label_options[:description], class: "description") if label_options.fetch(:description, nil).present?
|
565
|
+
wrapper(content, class: "label-wrap")
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
def label_text(name, options = {})
|
570
|
+
if options[:label_text].present?
|
571
|
+
options[:label_text]
|
572
|
+
else
|
573
|
+
if options[:translation_key].present?
|
574
|
+
key = options[:translation_key]
|
575
|
+
else
|
576
|
+
key = name.to_s.sub(/_uid$/, '')
|
577
|
+
end
|
578
|
+
|
579
|
+
translate_attribute(key)
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
def translate_attribute(attribute)
|
584
|
+
object.class.human_attribute_name(attribute, create_default: false)
|
585
|
+
end
|
586
|
+
|
587
|
+
def association_collection(reflector)
|
588
|
+
object.send(reflector.name)
|
589
|
+
end
|
590
|
+
|
591
|
+
def sortable_column_name
|
592
|
+
'item_position'
|
593
|
+
end
|
594
|
+
end
|