avo 2.43.0 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +30 -26
- data/Gemfile.lock +235 -161
- data/README.md +19 -27
- data/Rakefile +2 -0
- data/app/assets/stylesheets/avo.base.css +1 -1
- data/app/assets/svgs/font.svg +1 -0
- data/app/assets/svgs/triangle-up.svg +1 -0
- data/app/components/avo/actions_component.html.erb +19 -5
- data/app/components/avo/actions_component.rb +39 -19
- data/app/components/avo/asset_manager/javascript_component.html.erb +3 -0
- data/app/components/avo/asset_manager/javascript_component.rb +13 -0
- data/app/components/avo/asset_manager/stylesheet_component.html.erb +3 -0
- data/app/components/avo/asset_manager/stylesheet_component.rb +13 -0
- data/app/components/avo/base_component.rb +15 -12
- data/app/components/avo/button_component.rb +20 -3
- data/app/components/avo/empty_state_component.rb +1 -1
- data/app/components/avo/field_wrapper_component.html.erb +1 -1
- data/app/components/avo/field_wrapper_component.rb +9 -15
- data/app/components/avo/fields/area_field/edit_component.html.erb +2 -2
- data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +75 -79
- data/app/components/avo/fields/belongs_to_field/edit_component.rb +7 -7
- data/app/components/avo/fields/belongs_to_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/belongs_to_field/show_component.rb +2 -2
- data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +3 -3
- data/app/components/avo/fields/common/badge_viewer_component.rb +1 -1
- data/app/components/avo/fields/common/boolean_check_component.html.erb +1 -12
- data/app/components/avo/fields/common/boolean_check_component.rb +2 -1
- data/app/components/avo/fields/common/boolean_group_component.html.erb +2 -2
- data/app/components/avo/fields/common/files/view_type/grid_item_component.rb +2 -2
- data/app/components/avo/fields/common/gravatar_viewer_component.html.erb +1 -1
- data/app/components/avo/fields/common/gravatar_viewer_component.rb +2 -2
- data/app/components/avo/fields/common/heading_component.html.erb +3 -8
- data/app/components/avo/fields/common/heading_component.rb +1 -3
- data/app/components/avo/fields/common/key_value_component.html.erb +2 -2
- data/app/components/avo/fields/common/key_value_component.rb +2 -2
- data/app/components/avo/fields/common/progress_bar_component.rb +3 -9
- data/app/components/avo/fields/common/status_viewer_component.html.erb +3 -0
- data/app/components/avo/fields/edit_component.rb +2 -2
- data/app/components/avo/fields/external_image_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/file_field/index_component.html.erb +2 -2
- data/app/components/avo/fields/gravatar_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/has_one_field/show_component.html.erb +3 -2
- data/app/components/avo/fields/has_one_field/show_component.rb +2 -2
- data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/heading_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/id_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/index_component.rb +6 -6
- data/app/components/avo/fields/location_field/edit_component.html.erb +12 -10
- data/app/components/avo/fields/preview_field/index_component.html.erb +10 -0
- data/app/components/avo/fields/preview_field/index_component.rb +4 -0
- data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
- data/app/components/avo/fields/show_component.rb +5 -2
- data/app/components/avo/fields/text_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -2
- data/app/components/avo/fields/trix_field/edit_component.rb +1 -1
- data/app/components/avo/fields/trix_field/show_component.html.erb +1 -1
- data/app/components/avo/filters_component.html.erb +9 -3
- data/app/components/avo/filters_component.rb +4 -4
- data/app/components/avo/index/field_wrapper_component.rb +1 -13
- data/app/components/avo/index/grid_item_component.html.erb +13 -36
- data/app/components/avo/index/grid_item_component.rb +43 -16
- data/app/components/avo/index/resource_controls_component.html.erb +3 -81
- data/app/components/avo/index/resource_controls_component.rb +125 -18
- data/app/components/avo/index/resource_grid_component.html.erb +5 -3
- data/app/components/avo/index/resource_grid_component.rb +5 -2
- data/app/components/avo/index/resource_map_component.html.erb +1 -1
- data/app/components/avo/index/resource_map_component.rb +3 -3
- data/app/components/avo/index/resource_table_component.html.erb +5 -4
- data/app/components/avo/index/resource_table_component.rb +24 -7
- data/app/components/avo/index/table_row_component.html.erb +9 -5
- data/app/components/avo/index/table_row_component.rb +3 -2
- data/app/components/avo/items/panel_component.html.erb +25 -0
- data/app/components/avo/items/panel_component.rb +43 -0
- data/app/components/avo/items/switcher_component.html.erb +17 -0
- data/app/components/avo/items/switcher_component.rb +79 -0
- data/app/components/avo/items/visible_items_component.html.erb +10 -0
- data/app/components/avo/items/visible_items_component.rb +11 -0
- data/app/components/avo/modal_component.html.erb +3 -4
- data/app/components/avo/paginator_component.html.erb +29 -40
- data/app/components/avo/paginator_component.rb +23 -5
- data/app/components/avo/panel_component.html.erb +7 -5
- data/app/components/avo/referrer_params_component.html.erb +1 -1
- data/app/components/avo/resource_component.rb +205 -26
- data/app/components/avo/resource_sidebar_component.html.erb +15 -18
- data/app/components/avo/resource_sidebar_component.rb +5 -3
- data/app/components/avo/sidebar/link_component.rb +1 -1
- data/app/components/avo/sidebar_component.html.erb +10 -3
- data/app/components/avo/sidebar_component.rb +5 -3
- data/app/components/avo/sidebar_profile_component.html.erb +18 -12
- data/app/components/avo/tab_group_component.html.erb +14 -8
- data/app/components/avo/tab_group_component.rb +1 -6
- data/app/components/avo/tab_switcher_component.html.erb +17 -40
- data/app/components/avo/tab_switcher_component.rb +6 -41
- data/app/components/avo/views/resource_edit_component.html.erb +23 -84
- data/app/components/avo/views/resource_edit_component.rb +20 -19
- data/app/components/avo/views/resource_index_component.html.erb +42 -47
- data/app/components/avo/views/resource_index_component.rb +76 -13
- data/app/components/avo/views/resource_show_component.html.erb +16 -177
- data/app/components/avo/views/resource_show_component.rb +16 -10
- data/app/controllers/avo/actions_controller.rb +37 -41
- data/app/controllers/avo/application_controller.rb +119 -181
- data/app/controllers/avo/associations_controller.rb +34 -43
- data/app/controllers/avo/attachments_controller.rb +4 -4
- data/app/controllers/avo/base_controller.rb +145 -98
- data/app/controllers/avo/debug_controller.rb +17 -5
- data/app/controllers/avo/home_controller.rb +1 -1
- data/app/controllers/avo/search_controller.rb +56 -50
- data/app/controllers/concerns/avo/initializes_avo.rb +22 -0
- data/app/helpers/avo/application_helper.rb +18 -8
- data/app/helpers/avo/resources_helper.rb +1 -1
- data/app/helpers/avo/url_helpers.rb +28 -12
- data/app/javascript/avo.base.js +1 -0
- data/app/javascript/js/application.js +3 -0
- data/app/javascript/js/controllers/action_controller.js +3 -1
- data/app/javascript/js/controllers/actions_overflow_controller.js +62 -0
- data/app/javascript/js/controllers/fields/reload_belongs_to_field_controller.js +7 -7
- data/app/javascript/js/controllers/filter_controller.js +1 -1
- data/app/javascript/js/controllers/input_autofocus_controller.js +12 -0
- data/app/javascript/js/controllers/preview_controller.js +24 -0
- data/app/javascript/js/controllers/search_controller.js +4 -2
- data/app/javascript/js/controllers/self_destroy_controller.js +7 -0
- data/app/javascript/js/controllers/toggle_controller.js +48 -0
- data/app/javascript/js/controllers.js +11 -5
- data/app/javascript/js/custom-stream-actions.js +15 -0
- data/app/views/avo/actions/show.html.erb +10 -7
- data/app/views/avo/associations/new.html.erb +2 -2
- data/app/views/avo/base/_new_via_belongs_to.html.erb +1 -1
- data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +3 -3
- data/app/views/avo/base/create_fail_action.turbo_stream.erb +2 -2
- data/app/views/avo/base/edit.html.erb +1 -1
- data/app/views/avo/base/index.html.erb +4 -3
- data/app/views/avo/base/new.html.erb +2 -1
- data/app/views/avo/base/preview.html.erb +19 -0
- data/app/views/avo/base/show.html.erb +2 -2
- data/app/views/avo/debug/_valid_indicator.html.erb +9 -0
- data/app/views/avo/debug/report.html.erb +32 -17
- data/app/views/avo/debug/{index.html.erb → status.html.erb} +31 -14
- data/app/views/avo/partials/_custom_tools_alert.html.erb +2 -2
- data/app/views/avo/partials/_flash_alerts.turbo_stream.erb +1 -1
- data/app/views/avo/partials/_footer.html.erb +1 -1
- data/app/views/avo/partials/_javascript.html.erb +5 -0
- data/app/views/avo/partials/_logo.html.erb +1 -1
- data/app/views/avo/partials/_navbar.html.erb +3 -5
- data/app/views/avo/partials/_resource_search.html.erb +1 -0
- data/app/views/avo/partials/_table_header.html.erb +5 -11
- data/app/views/layouts/avo/application.html.erb +5 -4
- data/avo.gemspec +11 -8
- data/bin/dev +3 -1
- data/bin/prod +0 -0
- data/config/i18n-tasks.yml +1 -1
- data/config/initializers/pagy.rb +2 -0
- data/config/master.key +1 -0
- data/config/routes.rb +7 -10
- data/db/factories.rb +6 -0
- data/lib/avo/asset_manager.rb +30 -0
- data/lib/avo/base_action.rb +84 -82
- data/lib/avo/base_resource.rb +286 -225
- data/lib/avo/base_resource_tool.rb +9 -16
- data/lib/avo/concerns/borrow_items_holder.rb +35 -0
- data/lib/avo/concerns/breadcrumbs.rb +2 -2
- data/lib/avo/concerns/{can_replace_fields.rb → can_replace_items.rb} +5 -9
- data/lib/avo/concerns/filters_session_handler.rb +7 -5
- data/lib/avo/concerns/has_controls.rb +37 -0
- data/lib/avo/concerns/has_description.rb +23 -0
- data/lib/avo/concerns/has_helpers.rb +18 -0
- data/lib/avo/concerns/has_item_type.rb +42 -0
- data/lib/avo/concerns/has_items.rb +339 -0
- data/lib/avo/concerns/hydration.rb +17 -0
- data/lib/avo/concerns/is_resource_item.rb +16 -36
- data/lib/avo/concerns/is_visible.rb +15 -0
- data/lib/avo/concerns/model_class_constantized.rb +0 -2
- data/lib/avo/concerns/pagination.rb +53 -0
- data/lib/avo/concerns/visible_in_different_views.rb +132 -0
- data/lib/avo/concerns/visible_items.rb +7 -38
- data/lib/avo/configuration/branding.rb +0 -12
- data/lib/avo/configuration.rb +28 -11
- data/lib/avo/current.rb +39 -0
- data/lib/avo/dsl/field_parser.rb +3 -3
- data/lib/avo/dynamic_router.rb +18 -3
- data/lib/avo/engine.rb +35 -30
- data/lib/avo/error_manager.rb +25 -0
- data/lib/avo/execution_context.rb +14 -15
- data/lib/avo/fields/base_field.rb +84 -115
- data/lib/avo/fields/belongs_to_field.rb +19 -23
- data/lib/avo/fields/concerns/file_authorization.rb +2 -2
- data/lib/avo/fields/concerns/handles_field_args.rb +49 -0
- data/lib/avo/fields/concerns/has_default.rb +1 -5
- data/lib/avo/fields/concerns/has_field_name.rb +22 -0
- data/lib/avo/fields/concerns/has_html_attributes.rb +112 -0
- data/lib/avo/fields/concerns/is_disabled.rb +1 -5
- data/lib/avo/fields/concerns/is_readonly.rb +1 -5
- data/lib/avo/fields/concerns/is_required.rb +5 -7
- data/lib/avo/fields/concerns/is_searchable.rb +15 -0
- data/lib/avo/fields/concerns/use_resource.rb +5 -1
- data/lib/avo/fields/concerns/use_view_components.rb +45 -0
- data/lib/avo/fields/country_field.rb +4 -0
- data/lib/avo/fields/date_time_field.rb +1 -5
- data/lib/avo/fields/external_image_field.rb +2 -2
- data/lib/avo/fields/field_manager.rb +55 -0
- data/lib/avo/fields/file_field.rb +2 -2
- data/lib/avo/fields/gravatar_field.rb +2 -2
- data/lib/avo/fields/has_and_belongs_to_many_field.rb +1 -2
- data/lib/avo/fields/has_base_field.rb +21 -17
- data/lib/avo/fields/has_many_field.rb +5 -2
- data/lib/avo/fields/has_one_field.rb +8 -12
- data/lib/avo/fields/heading_field.rb +9 -14
- data/lib/avo/fields/hidden_field.rb +1 -1
- data/lib/avo/fields/id_field.rb +3 -3
- data/lib/avo/fields/location_field.rb +10 -10
- data/lib/avo/fields/password_field.rb +1 -1
- data/lib/avo/fields/preview_field.rb +14 -0
- data/lib/avo/fields/select_field.rb +12 -8
- data/lib/avo/fields/status_field.rb +7 -1
- data/lib/avo/fields/text_field.rb +2 -2
- data/lib/avo/filters/base_filter.rb +9 -4
- data/lib/avo/html/builder.rb +8 -8
- data/lib/avo/item_grapher.rb +78 -0
- data/lib/avo/licensing/h_q.rb +11 -73
- data/lib/avo/licensing/license.rb +5 -1
- data/lib/avo/licensing/license_manager.rb +1 -1
- data/lib/avo/licensing/pro_license.rb +1 -7
- data/lib/avo/loaders/fields_loader.rb +7 -1
- data/lib/avo/plugin.rb +36 -0
- data/lib/avo/plugin_manager.rb +56 -0
- data/lib/avo/prefixed_test_helpers.rb +20 -0
- data/lib/avo/reloader.rb +3 -0
- data/lib/avo/resources/controls/actions_list.rb +7 -12
- data/lib/avo/resources/controls/attach_button.rb +15 -0
- data/lib/avo/resources/controls/back_button.rb +1 -1
- data/lib/avo/resources/controls/base_control.rb +15 -49
- data/lib/avo/resources/controls/create_button.rb +15 -0
- data/lib/avo/resources/controls/delete_button.rb +5 -1
- data/lib/avo/resources/controls/detach_button.rb +4 -1
- data/lib/avo/resources/controls/edit_button.rb +4 -1
- data/lib/avo/resources/controls/order_controls.rb +8 -0
- data/lib/avo/resources/controls/save_button.rb +13 -0
- data/lib/avo/resources/controls/show_button.rb +15 -0
- data/lib/avo/resources/items/holder.rb +96 -0
- data/lib/avo/resources/items/item_group.rb +44 -0
- data/lib/avo/resources/items/main_panel.rb +12 -0
- data/lib/avo/resources/items/panel.rb +2 -0
- data/lib/avo/resources/items/row.rb +42 -0
- data/lib/avo/resources/items/sidebar.rb +46 -0
- data/lib/avo/resources/items/tab.rb +54 -0
- data/lib/avo/resources/items/tab_group.rb +62 -0
- data/lib/avo/resources/resource_manager.rb +179 -0
- data/lib/avo/services/authorization_service.rb +11 -110
- data/lib/avo/services/debug_service.rb +93 -0
- data/lib/avo/services/encryption_service.rb +8 -12
- data/lib/avo/services/telemetry_service.rb +85 -0
- data/lib/avo/test_helpers.rb +362 -0
- data/lib/avo/tools/tool_manager.rb +30 -0
- data/lib/avo/version.rb +1 -1
- data/lib/avo/view_inquirer.rb +36 -0
- data/lib/avo.rb +109 -24
- data/lib/generators/avo/action_generator.rb +8 -8
- data/lib/generators/avo/card_generator.rb +27 -0
- data/lib/generators/avo/concerns/parent_controller.rb +20 -0
- data/lib/generators/avo/controller_generator.rb +3 -0
- data/lib/generators/avo/eject_generator.rb +180 -15
- data/lib/generators/avo/field_generator.rb +49 -2
- data/lib/generators/avo/filter_generator.rb +8 -8
- data/lib/generators/avo/js/install_generator.rb +2 -2
- data/lib/generators/avo/resource_generator.rb +12 -9
- data/lib/generators/avo/scope_generator.rb +15 -0
- data/lib/generators/avo/tailwindcss/install_generator.rb +70 -26
- data/lib/generators/avo/templates/action.tt +8 -6
- data/lib/generators/avo/templates/cards/chartkick_card.tt +1 -1
- data/lib/generators/avo/templates/cards/chartkick_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card.tt +1 -1
- data/lib/generators/avo/templates/cards/metric_card_sample.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card.tt +1 -1
- data/lib/generators/avo/templates/cards/partial_card_sample.tt +1 -1
- data/lib/generators/avo/templates/dashboards/dashboard.tt +5 -3
- data/lib/generators/avo/templates/field/%singular_name%_field.rb.tt +1 -1
- data/lib/generators/avo/templates/filters/boolean_filter.tt +1 -1
- data/lib/generators/avo/templates/filters/multiple_select_filter.tt +1 -1
- data/lib/generators/avo/templates/filters/select_filter.tt +1 -1
- data/lib/generators/avo/templates/filters/text_filter.tt +1 -1
- data/lib/generators/avo/templates/initializer/avo.tt +7 -3
- data/lib/generators/avo/templates/locales/avo.ar.yml +7 -6
- data/lib/generators/avo/templates/locales/avo.en.yml +6 -3
- data/lib/generators/avo/templates/locales/avo.es.yml +127 -0
- data/lib/generators/avo/templates/locales/avo.fr.yml +3 -0
- data/lib/generators/avo/templates/locales/avo.nb.yml +3 -0
- data/lib/generators/avo/templates/locales/avo.nn.yml +3 -0
- data/lib/generators/avo/templates/locales/avo.pt-BR.yml +3 -0
- data/lib/generators/avo/templates/locales/avo.pt.yml +3 -0
- data/lib/generators/avo/templates/locales/avo.ro.yml +8 -5
- data/lib/generators/avo/templates/locales/avo.tr.yml +3 -0
- data/lib/generators/avo/templates/resource/controller.tt +1 -1
- data/lib/generators/avo/templates/resource/resource.tt +7 -7
- data/lib/generators/avo/templates/resource_tools/partial.tt +2 -2
- data/lib/generators/avo/templates/resource_tools/resource_tool.tt +1 -1
- data/lib/generators/avo/templates/scope.tt +6 -0
- data/lib/generators/avo/templates/tailwindcss/Procfile.dev +1 -1
- data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +5 -3
- data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +11 -0
- data/lib/tasks/avo_tasks.rake +72 -4
- data/public/avo-assets/avo.base.css +1893 -1187
- data/public/avo-assets/avo.base.js +223 -311
- data/public/avo-assets/avo.base.js.map +3 -3
- data/public/avo-assets/avo.css +9744 -0
- data/public/avo-assets/avo.js +513 -0
- data/public/avo-assets/avo.js.map +7 -0
- data/tailwind.custom.js +47 -0
- data/tailwind.preset.js +152 -0
- metadata +121 -116
- data/app/components/avo/card_component.html.erb +0 -46
- data/app/components/avo/card_component.rb +0 -25
- data/app/components/avo/dashboards/divider_component.html.erb +0 -9
- data/app/components/avo/dashboards/divider_component.rb +0 -19
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.html.erb +0 -47
- data/app/components/avo/fields/belongs_to_field/autocomplete_component.rb +0 -95
- data/app/components/avo/fields/tags_field/edit_component.html.erb +0 -35
- data/app/components/avo/fields/tags_field/edit_component.rb +0 -4
- data/app/components/avo/fields/tags_field/index_component.html.erb +0 -10
- data/app/components/avo/fields/tags_field/index_component.rb +0 -9
- data/app/components/avo/fields/tags_field/show_component.html.erb +0 -7
- data/app/components/avo/fields/tags_field/show_component.rb +0 -5
- data/app/components/avo/fields/tags_field/tag_component.html.erb +0 -9
- data/app/components/avo/fields/tags_field/tag_component.rb +0 -11
- data/app/components/avo/index/ordering/base_component.rb +0 -9
- data/app/components/avo/index/ordering/button_component.html.erb +0 -11
- data/app/components/avo/index/ordering/button_component.rb +0 -23
- data/app/components/avo/index/ordering/buttons_component.html.erb +0 -32
- data/app/components/avo/index/ordering/buttons_component.rb +0 -47
- data/app/components/avo/item_switcher_component.html.erb +0 -27
- data/app/components/avo/item_switcher_component.rb +0 -48
- data/app/components/avo/sidebar/item_switcher_component.html.erb +0 -16
- data/app/components/avo/sidebar/item_switcher_component.rb +0 -15
- data/app/controllers/avo/dashboards/cards_controller.rb +0 -37
- data/app/controllers/avo/dashboards_controller.rb +0 -22
- data/app/controllers/avo/reorder_controller.rb +0 -25
- data/app/controllers/avo/team_users_controller.rb +0 -4
- data/app/javascript/js/controllers/base_controller.js +0 -22
- data/app/javascript/js/controllers/fields/tags_field_controller.js +0 -127
- data/app/javascript/js/controllers/toggle_panel_controller.js +0 -18
- data/app/views/avo/dashboards/cards/_chartkick_card.html.erb +0 -3
- data/app/views/avo/dashboards/cards/_metric_card.html.erb +0 -5
- data/app/views/avo/dashboards/cards/chartkick_missing.html.erb +0 -14
- data/app/views/avo/dashboards/cards/show.html.erb +0 -3
- data/app/views/avo/dashboards/show.html.erb +0 -38
- data/app/views/avo/partials/_global_search.html.erb +0 -19
- data/app/views/avo/sidebar/_license_warnings.html.erb +0 -6
- data/lib/avo/action_model.rb +0 -20
- data/lib/avo/app.rb +0 -237
- data/lib/avo/base_card.rb +0 -161
- data/lib/avo/concerns/fetches_things.rb +0 -150
- data/lib/avo/concerns/handles_field_args.rb +0 -47
- data/lib/avo/concerns/has_editable_controls.rb +0 -34
- data/lib/avo/concerns/has_fields.rb +0 -334
- data/lib/avo/concerns/has_html_attributes.rb +0 -108
- data/lib/avo/concerns/policy_helpers.rb +0 -31
- data/lib/avo/concerns/visible_in_dashboard.rb +0 -31
- data/lib/avo/dashboards/base_dashboard.rb +0 -89
- data/lib/avo/dashboards/base_divider.rb +0 -35
- data/lib/avo/dashboards/chartkick_card.rb +0 -77
- data/lib/avo/dashboards/dashboard_card.rb +0 -6
- data/lib/avo/dashboards/metric_card.rb +0 -9
- data/lib/avo/dashboards/partial_card.rb +0 -7
- data/lib/avo/fields/field_extensions/has_field_name.rb +0 -19
- data/lib/avo/fields/field_extensions/visible_in_different_views.rb +0 -111
- data/lib/avo/fields/tags_field.rb +0 -102
- data/lib/avo/grid_collector.rb +0 -42
- data/lib/avo/hosts/association_scope_host.rb +0 -8
- data/lib/avo/hosts/base_host.rb +0 -25
- data/lib/avo/hosts/card_visibility.rb +0 -20
- data/lib/avo/hosts/dashboard_card.rb +0 -22
- data/lib/avo/hosts/dashboard_visibility.rb +0 -19
- data/lib/avo/hosts/ordering.rb +0 -22
- data/lib/avo/hosts/record_host.rb +0 -7
- data/lib/avo/hosts/resource_record_host.rb +0 -7
- data/lib/avo/hosts/resource_view_record_host.rb +0 -7
- data/lib/avo/hosts/search_scope_host.rb +0 -7
- data/lib/avo/hosts/view_record_host.rb +0 -7
- data/lib/avo/hosts/visibility_host.rb +0 -12
- data/lib/avo/items_holder.rb +0 -96
- data/lib/avo/main_panel.rb +0 -3
- data/lib/avo/menu/base_item.rb +0 -25
- data/lib/avo/menu/builder.rb +0 -82
- data/lib/avo/menu/dashboard.rb +0 -22
- data/lib/avo/menu/group.rb +0 -2
- data/lib/avo/menu/link.rb +0 -6
- data/lib/avo/menu/menu.rb +0 -2
- data/lib/avo/menu/resource.rb +0 -22
- data/lib/avo/menu/section.rb +0 -2
- data/lib/avo/panel.rb +0 -24
- data/lib/avo/panel_builder.rb +0 -25
- data/lib/avo/resources/controls/action.rb +0 -38
- data/lib/avo/resources/controls/execution_context.rb +0 -58
- data/lib/avo/resources/controls/items_holder.rb +0 -19
- data/lib/avo/resources/controls/link_to.rb +0 -27
- data/lib/avo/row.rb +0 -26
- data/lib/avo/row_builder.rb +0 -24
- data/lib/avo/services/authorization_clients/nil_client.rb +0 -37
- data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
- data/lib/avo/sidebar.rb +0 -30
- data/lib/avo/sidebar_builder.rb +0 -24
- data/lib/avo/tab.rb +0 -72
- data/lib/avo/tab_builder.rb +0 -25
- data/lib/avo/tab_group.rb +0 -42
- data/lib/avo/tab_group_builder.rb +0 -43
- data/lib/avo/tools_manager.rb +0 -11
- data/lib/generators/avo/card/chartkick_generator.rb +0 -18
- data/lib/generators/avo/card/metric_generator.rb +0 -18
- data/lib/generators/avo/card/partial_generator.rb +0 -19
- data/lib/generators/avo/templates/js/avo.custom.js +0 -2
- data/lib/generators/avo/templates/standalone_action.tt +0 -8
- /data/app/assets/stylesheets/css/{tags.css → fields/tags.css} +0 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
class Avo::Resources::Items::Holder
|
2
|
+
attr_reader :tools, :from
|
3
|
+
attr_accessor :items
|
4
|
+
attr_accessor :invalid_fields
|
5
|
+
|
6
|
+
def initialize(from: nil, parent: nil)
|
7
|
+
@items = []
|
8
|
+
@items_index = 0
|
9
|
+
@invalid_fields = []
|
10
|
+
@from = from
|
11
|
+
@parent = parent
|
12
|
+
end
|
13
|
+
|
14
|
+
# Adds a field to the items_holder
|
15
|
+
def field(field_name, **args, &block)
|
16
|
+
# If the field is paresed inside a tab group, add it to the tab
|
17
|
+
# This will happen when the field is parsed inside a tab group from a resource method
|
18
|
+
if from.present? && from.class == Avo::Resources::Items::TabGroup::Builder
|
19
|
+
return from.field(field_name, holder: self, **args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
field_parser = Avo::Dsl::FieldParser.new(id: field_name, order_index: @items_index, **args, &block).parse
|
23
|
+
|
24
|
+
if field_parser.invalid?
|
25
|
+
as = args.fetch(:as, nil)
|
26
|
+
|
27
|
+
# End execution ehre and add the field to the invalid_fileds payload so we know to wanr the developer about that.
|
28
|
+
# @todo: Make sure this warning is still active
|
29
|
+
return add_invalid_field({
|
30
|
+
name: field_name,
|
31
|
+
as: as,
|
32
|
+
# resource: resource_class.name,
|
33
|
+
message: "There's an invalid field configuration for this resource. <br/> <code class='px-1 py-px rounded bg-red-600'>field :#{field_name}, as: :#{as}</code>"
|
34
|
+
})
|
35
|
+
end
|
36
|
+
|
37
|
+
add_item field_parser.instance
|
38
|
+
end
|
39
|
+
|
40
|
+
def tabs(tab = nil, **kwargs, &block)
|
41
|
+
if tab.present?
|
42
|
+
add_item tab
|
43
|
+
else
|
44
|
+
add_item Avo::Resources::Items::TabGroup::Builder.parse_block(parent: @parent, **kwargs, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def tab(name, **args, &block)
|
49
|
+
add_item Avo::Resources::Items::Tab::Builder.parse_block(name: name, parent: @parent, **args, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def row(**args, &block)
|
53
|
+
add_item Avo::Resources::Items::Row::Builder.parse_block(parent: @parent, **args, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
def tool(klass, **args)
|
57
|
+
add_item klass.new(**args)
|
58
|
+
end
|
59
|
+
|
60
|
+
def panel(panel_name = nil, **args, &block)
|
61
|
+
add_item Avo::Resources::Items::ItemGroup::Builder.parse_block(name: panel_name, parent: @parent, **args, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
# The main panel is the one that also render the header of the resource with the breadcrumbs, the title and the controls.
|
65
|
+
def main_panel(**args, &block)
|
66
|
+
add_item Avo::Resources::Items::MainPanel::Builder.parse_block(name: "main_panel", parent: @parent, **args, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def sidebar(**args, &block)
|
70
|
+
check_sidebar_is_inside_a_panel
|
71
|
+
|
72
|
+
add_item Avo::Resources::Items::Sidebar::Builder.parse_block(parent: @parent, **args, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_item(instance)
|
76
|
+
@items << instance
|
77
|
+
|
78
|
+
increment_order_index
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def add_invalid_field(payload)
|
84
|
+
invalid_fields << payload
|
85
|
+
end
|
86
|
+
|
87
|
+
def increment_order_index
|
88
|
+
@items_index += 1
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_sidebar_is_inside_a_panel
|
92
|
+
unless @from.eql?(Avo::Resources::Items::Panel::Builder) || @from.eql?(Avo::Resources::Items::MainPanel::Builder)
|
93
|
+
raise "The sidebar must be inside a panel."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Avo::Resources::Items::ItemGroup
|
2
|
+
prepend Avo::Concerns::IsResourceItem
|
3
|
+
|
4
|
+
include Avo::Concerns::HasItems
|
5
|
+
include Avo::Concerns::HasItemType
|
6
|
+
include Avo::Concerns::VisibleItems
|
7
|
+
include Avo::Concerns::VisibleInDifferentViews
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :description
|
11
|
+
|
12
|
+
delegate :items, :add_item, to: :items_holder
|
13
|
+
|
14
|
+
def initialize(name: nil, description: nil, view: nil, **args)
|
15
|
+
@name = name
|
16
|
+
@view = Avo::ViewInquirer.new view
|
17
|
+
@description = description
|
18
|
+
@items_holder = Avo::Resources::Items::Holder.new
|
19
|
+
@args = args
|
20
|
+
|
21
|
+
post_initialize if respond_to?(:post_initialize)
|
22
|
+
end
|
23
|
+
|
24
|
+
class Builder
|
25
|
+
include Avo::Concerns::BorrowItemsHolder
|
26
|
+
|
27
|
+
delegate :heading, to: :items_holder
|
28
|
+
delegate :field, to: :items_holder
|
29
|
+
delegate :row, to: :items_holder
|
30
|
+
delegate :items, to: :items_holder
|
31
|
+
delegate :sidebar, to: :items_holder
|
32
|
+
|
33
|
+
def initialize(parent:, name: nil, **args)
|
34
|
+
@panel = Avo::Resources::Items::Panel.new(name: name, **args)
|
35
|
+
@items_holder = Avo::Resources::Items::Holder.new(from: self.class, parent: parent)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Fetch the tab
|
39
|
+
def build
|
40
|
+
@panel.items_holder = @items_holder
|
41
|
+
@panel
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Avo::Resources::Items::MainPanel < Avo::Resources::Items::Panel
|
2
|
+
class Builder < Avo::Resources::Items::ItemGroup::Builder
|
3
|
+
def initialize(parent: ,**args)
|
4
|
+
@panel = Avo::Resources::Items::MainPanel.new(**args)
|
5
|
+
@items_holder = Avo::Resources::Items::Holder.new(from: self.class, parent: parent)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def visible?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Avo::Resources::Items::Row
|
2
|
+
include Avo::Concerns::IsResourceItem
|
3
|
+
include Avo::Concerns::HasItems
|
4
|
+
include Avo::Concerns::HasItemType
|
5
|
+
include Avo::Concerns::VisibleItems
|
6
|
+
include Avo::Concerns::Hydration
|
7
|
+
|
8
|
+
class_attribute :item_type, default: :row
|
9
|
+
|
10
|
+
attr_reader :view
|
11
|
+
attr_accessor :items_holder
|
12
|
+
|
13
|
+
delegate :items, :add_item, to: :items_holder
|
14
|
+
|
15
|
+
def initialize(view: nil)
|
16
|
+
@view = Avo::ViewInquirer.new view
|
17
|
+
@items_holder = Avo::Resources::Items::Holder.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_items?
|
21
|
+
@items.present?
|
22
|
+
end
|
23
|
+
|
24
|
+
class Builder
|
25
|
+
include Avo::Concerns::BorrowItemsHolder
|
26
|
+
|
27
|
+
delegate :field, to: :items_holder
|
28
|
+
delegate :tool, to: :items_holder
|
29
|
+
delegate :items, to: :items_holder
|
30
|
+
|
31
|
+
def initialize(parent:, **args)
|
32
|
+
@row = Avo::Resources::Items::Row.new(**args)
|
33
|
+
@items_holder = Avo::Resources::Items::Holder.new(parent: @parent)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Fetch the tab
|
37
|
+
def build
|
38
|
+
@row.items_holder = @items_holder
|
39
|
+
@row
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Avo::Resources::Items::Sidebar
|
2
|
+
prepend Avo::Concerns::IsResourceItem
|
3
|
+
|
4
|
+
include Avo::Concerns::HasItems
|
5
|
+
include Avo::Concerns::HasItemType
|
6
|
+
include Avo::Concerns::IsVisible
|
7
|
+
include Avo::Concerns::VisibleInDifferentViews
|
8
|
+
|
9
|
+
delegate :items, :add_item, to: :items_holder
|
10
|
+
|
11
|
+
attr_reader :name
|
12
|
+
|
13
|
+
def initialize(name: nil, view: nil, **args)
|
14
|
+
@name = name
|
15
|
+
@items_holder = Avo::Resources::Items::Holder.new
|
16
|
+
@view = Avo::ViewInquirer.new view
|
17
|
+
@panel_wrapper = args[:panel_wrapper].nil? ? true : args[:panel_wrapper]
|
18
|
+
@args = args
|
19
|
+
|
20
|
+
post_initialize if respond_to?(:post_initialize)
|
21
|
+
end
|
22
|
+
|
23
|
+
def panel_wrapper?
|
24
|
+
@panel_wrapper
|
25
|
+
end
|
26
|
+
|
27
|
+
class Builder
|
28
|
+
include Avo::Concerns::BorrowItemsHolder
|
29
|
+
|
30
|
+
delegate :field, to: :items_holder
|
31
|
+
delegate :tool, to: :items_holder
|
32
|
+
delegate :items, to: :items_holder
|
33
|
+
delegate :heading, to: :items_holder
|
34
|
+
|
35
|
+
def initialize(parent: , name: nil, **args)
|
36
|
+
@sidebar = Avo::Resources::Items::Sidebar.new(**args)
|
37
|
+
@items_holder = Avo::Resources::Items::Holder.new(parent: parent)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Fetch the sidebar
|
41
|
+
def build
|
42
|
+
@sidebar.items_holder = @items_holder
|
43
|
+
@sidebar
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Avo::Resources::Items::Tab
|
2
|
+
prepend Avo::Concerns::IsResourceItem
|
3
|
+
|
4
|
+
include Avo::Concerns::HasItems
|
5
|
+
include Avo::Concerns::HasItemType
|
6
|
+
include Avo::Concerns::VisibleItems
|
7
|
+
include Avo::Concerns::VisibleInDifferentViews
|
8
|
+
|
9
|
+
delegate :items, :add_item, to: :items_holder
|
10
|
+
|
11
|
+
attr_accessor :description
|
12
|
+
|
13
|
+
def initialize(name: nil, description: nil, view: nil, **args)
|
14
|
+
@name = name
|
15
|
+
@description = description
|
16
|
+
@items_holder = Avo::Resources::Items::Holder.new
|
17
|
+
@view = Avo::ViewInquirer.new view
|
18
|
+
@args = args
|
19
|
+
|
20
|
+
post_initialize if respond_to?(:post_initialize)
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
Avo::ExecutionContext.new(target: @name).handle
|
25
|
+
end
|
26
|
+
|
27
|
+
def turbo_frame_id(parent: nil)
|
28
|
+
id = "#{Avo::Resources::Items::Tab.to_s.parameterize} #{name}".parameterize
|
29
|
+
|
30
|
+
return id if parent.nil?
|
31
|
+
|
32
|
+
"#{parent.turbo_frame_id} #{id}".parameterize
|
33
|
+
end
|
34
|
+
|
35
|
+
class Builder
|
36
|
+
include Avo::Concerns::BorrowItemsHolder
|
37
|
+
|
38
|
+
delegate :field, to: :items_holder
|
39
|
+
delegate :tool, to: :items_holder
|
40
|
+
delegate :panel, to: :items_holder
|
41
|
+
delegate :items, to: :items_holder
|
42
|
+
|
43
|
+
def initialize(parent:, name: nil, **args)
|
44
|
+
@tab = Avo::Resources::Items::Tab.new(name: name, **args)
|
45
|
+
@items_holder = Avo::Resources::Items::Holder.new(parent: parent)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Fetch the tab
|
49
|
+
def build
|
50
|
+
@tab.items_holder = @items_holder
|
51
|
+
@tab
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class Avo::Resources::Items::TabGroup
|
2
|
+
prepend Avo::Concerns::IsResourceItem
|
3
|
+
|
4
|
+
include Avo::Concerns::HasItems
|
5
|
+
include Avo::Concerns::HasItemType
|
6
|
+
include Avo::Concerns::IsVisible
|
7
|
+
include Avo::Concerns::VisibleInDifferentViews
|
8
|
+
|
9
|
+
attr_accessor :index
|
10
|
+
attr_accessor :style
|
11
|
+
|
12
|
+
def initialize(index: 0, view: nil, style: nil, **args)
|
13
|
+
@index = index
|
14
|
+
@items_holder = Avo::Resources::Items::Holder.new
|
15
|
+
@view = Avo::ViewInquirer.new view
|
16
|
+
@style = style
|
17
|
+
@args = args
|
18
|
+
|
19
|
+
post_initialize if respond_to?(:post_initialize)
|
20
|
+
end
|
21
|
+
|
22
|
+
def turbo_frame_id
|
23
|
+
"#{Avo::Resources::Items::TabGroup.to_s.parameterize} #{index}".parameterize
|
24
|
+
end
|
25
|
+
|
26
|
+
class Builder
|
27
|
+
include Avo::Concerns::BorrowItemsHolder
|
28
|
+
|
29
|
+
delegate :tab, to: :items_holder
|
30
|
+
|
31
|
+
def field(field_name, **args, &block)
|
32
|
+
parsed = Avo::Dsl::FieldParser.new(id: field_name, order_index: @items_index, **args, &block).parse
|
33
|
+
field_instance = parsed.instance
|
34
|
+
|
35
|
+
name = field_instance.name
|
36
|
+
tab = Avo::Resources::Items::Tab.new name: name
|
37
|
+
|
38
|
+
if field_instance.has_own_panel?
|
39
|
+
tab.items_holder.add_item parsed.instance
|
40
|
+
else
|
41
|
+
# If the field is not in a panel, create one and add it
|
42
|
+
panel = Avo::Resources::Items::Panel.new name: name
|
43
|
+
panel.items_holder.add_item parsed.instance
|
44
|
+
# Add that panel to the items_holder
|
45
|
+
tab.items_holder.add_item panel
|
46
|
+
end
|
47
|
+
|
48
|
+
@items_holder.tabs tab
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(parent: ,style: nil)
|
52
|
+
@group = Avo::Resources::Items::TabGroup.new(style: style)
|
53
|
+
@items_holder = Avo::Resources::Items::Holder.new(parent: parent, from: self)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Fetch the tab
|
57
|
+
def build
|
58
|
+
@group.items_holder = @items_holder
|
59
|
+
@group
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module Avo
|
2
|
+
module Resources
|
3
|
+
class ResourceManager
|
4
|
+
attr_accessor :resources
|
5
|
+
|
6
|
+
alias_method :all, :resources
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def build
|
10
|
+
instance = new
|
11
|
+
instance.init_resources
|
12
|
+
instance.check_bad_resources
|
13
|
+
instance
|
14
|
+
end
|
15
|
+
|
16
|
+
# Fetches the resources available to the application.
|
17
|
+
# We have two ways of doing that.
|
18
|
+
#
|
19
|
+
# 1. Through eager loading.
|
20
|
+
# We automatically eager load the resources directory and fetch the descendants from the scanned files.
|
21
|
+
# This is the simple way to get started.
|
22
|
+
#
|
23
|
+
# 2. Manually, declared by the user.
|
24
|
+
# We have this option to load the resources because when they are loaded automatically through eager loading,
|
25
|
+
# those Resource classes and their methods may trigger loading other classes. And that may disrupt Rails booting process.
|
26
|
+
# Ex: AdminResource may use self.model_class = User. That will trigger Ruby to load the User class and itself load
|
27
|
+
# other classes in a chain reaction.
|
28
|
+
# The scenario that comes up most often is when Rails boots, the routes are being computed which eager loads the resource files.
|
29
|
+
# At that boot time some migration might have not been run yet, but Rails tries to access them through model associations,
|
30
|
+
# and they are not available.
|
31
|
+
#
|
32
|
+
# To enable this feature add a `resources` array config in your Avo initializer.
|
33
|
+
# config.resources = [
|
34
|
+
# "UserResource",
|
35
|
+
# "FishResource",
|
36
|
+
# ]
|
37
|
+
def fetch_resources
|
38
|
+
resources = if Avo.configuration.resources.nil?
|
39
|
+
BaseResource.descendants
|
40
|
+
else
|
41
|
+
Avo.configuration.resources
|
42
|
+
end
|
43
|
+
|
44
|
+
resources.map do |resource|
|
45
|
+
if resource.is_a?(Class)
|
46
|
+
resource
|
47
|
+
else
|
48
|
+
resource.to_s.safe_constantize
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
@resources = []
|
56
|
+
end
|
57
|
+
|
58
|
+
def init_resources
|
59
|
+
self.resources = self.class.fetch_resources
|
60
|
+
.reject do |resource|
|
61
|
+
# Remove the BaseResource. We only need the descendants
|
62
|
+
resource == Avo::BaseResource
|
63
|
+
end
|
64
|
+
.uniq do |klass|
|
65
|
+
# On invalid resource configuration the resource classes get duplicated in `ObjectSpace`
|
66
|
+
# We need to de-duplicate them
|
67
|
+
klass.name
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_bad_resources
|
72
|
+
resources.each do |resource|
|
73
|
+
has_model = resource.model_class.present?
|
74
|
+
|
75
|
+
unless has_model
|
76
|
+
possible_model = resource.to_s.gsub "Avo::Resources::", ""
|
77
|
+
possible_model = possible_model.gsub "Resource", ""
|
78
|
+
|
79
|
+
Avo.error_manager.add({
|
80
|
+
url: "https://docs.avohq.io/2.0/resources.html#custom-model-class",
|
81
|
+
target: "_blank",
|
82
|
+
message: "#{resource} does not have a valid model assigned. It failed to find the #{possible_model} model. \n\r Please create that model or assign one using self.model_class = YOUR_MODEL"
|
83
|
+
})
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Filters out the resources that are missing the model_class
|
89
|
+
def valid_resources
|
90
|
+
resources.select { |resource| resource.model_class.present? }.sort_by(&:name)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the Avo resource by camelized name
|
94
|
+
#
|
95
|
+
# get_resource_by_name('User') => instance of Avo::Resources::User
|
96
|
+
def get_resource(resource)
|
97
|
+
resource = "Avo::Resources::#{resource}" unless resource.to_s.starts_with?("Avo::Resources::")
|
98
|
+
|
99
|
+
resources.find do |available_resource|
|
100
|
+
resource.to_s == available_resource.to_s
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the Avo resource by singular snake_cased name
|
105
|
+
#
|
106
|
+
# get_resource_by_name('user') => instance of Avo::Resources::User
|
107
|
+
def get_resource_by_name(name)
|
108
|
+
get_resource name.singularize.camelize
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns the Avo resource by singular snake_cased name
|
112
|
+
# From all the resources that use the same model_class, it will fetch the first one in alphabetical order
|
113
|
+
#
|
114
|
+
# get_resource_by_name('User') => instance of Avo::Resources::User
|
115
|
+
# get_resource_by_name(User) => instance of Avo::Resources::User
|
116
|
+
|
117
|
+
def get_resource_by_model_class(klass)
|
118
|
+
# Fetch the mappings imposed by the user.
|
119
|
+
# If they are present, use those ones.
|
120
|
+
mapping = get_mapping_for_model klass
|
121
|
+
return get_resource(mapping) if mapping.present?
|
122
|
+
|
123
|
+
valid_resources
|
124
|
+
.find do |resource|
|
125
|
+
resource.model_class.model_name.name == klass.to_s
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns the Avo resource by singular snake_cased name
|
130
|
+
#
|
131
|
+
# get_resource_by_controller_name('delayed_backend_active_record_jobs') => instance of Avo::Resources::DelayedJob
|
132
|
+
# get_resource_by_controller_name('users') => instance of Avo::Resources::User
|
133
|
+
def get_resource_by_controller_name(name)
|
134
|
+
valid_resources
|
135
|
+
.find do |resource|
|
136
|
+
resource.model_class.to_s.pluralize.underscore.tr("/", "_") == name.to_s
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the Avo resource by some name
|
141
|
+
def guess_resource(name)
|
142
|
+
get_resource_by_name(name.to_s) || get_resource_by_model_class(name)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns the Rails model class by singular snake_cased name
|
146
|
+
#
|
147
|
+
# get_model_class_by_name('user') => User
|
148
|
+
def get_model_class_by_name(name)
|
149
|
+
name.to_s.camelize.singularize
|
150
|
+
end
|
151
|
+
|
152
|
+
def get_available_resources(user = nil)
|
153
|
+
valid_resources
|
154
|
+
.select do |resource|
|
155
|
+
resource.authorization.class.authorize(
|
156
|
+
user,
|
157
|
+
resource.model_class,
|
158
|
+
Avo.configuration.authorization_methods.stringify_keys["index"],
|
159
|
+
raise_exception: false
|
160
|
+
)
|
161
|
+
end
|
162
|
+
.sort_by { |r| r.name }
|
163
|
+
end
|
164
|
+
|
165
|
+
def resources_for_navigation(user = nil)
|
166
|
+
get_available_resources(user)
|
167
|
+
.select do |resource|
|
168
|
+
resource.visible_on_sidebar
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def get_mapping_for_model(klass)
|
175
|
+
(Avo.configuration.model_resource_mapping || {}).stringify_keys.transform_values(&:to_s)[klass.to_s]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -6,109 +6,19 @@ module Avo
|
|
6
6
|
attr_accessor :policy_class
|
7
7
|
|
8
8
|
class << self
|
9
|
-
def
|
10
|
-
client = Avo.configuration.authorization_client
|
11
|
-
|
12
|
-
client = nil if Avo::App.license.lacks(:authorization)
|
13
|
-
|
14
|
-
klass = case client
|
15
|
-
when nil
|
16
|
-
nil_client
|
17
|
-
when :pundit
|
18
|
-
pundit_client
|
19
|
-
else
|
20
|
-
if client.is_a?(String)
|
21
|
-
client.safe_constantize
|
22
|
-
else
|
23
|
-
client
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
klass.new
|
28
|
-
end
|
29
|
-
|
30
|
-
def authorize(user, record, action, policy_class: nil, **args)
|
31
|
-
return true if skip_authorization
|
32
|
-
|
33
|
-
client.authorize user, record, action, policy_class: policy_class
|
34
|
-
|
9
|
+
def authorize(*args, **kwargs)
|
35
10
|
true
|
36
|
-
rescue NoPolicyError => error
|
37
|
-
# By default, Avo allows anything if you don't have a policy present.
|
38
|
-
return true unless Avo.configuration.raise_error_on_missing_policy
|
39
|
-
|
40
|
-
raise error
|
41
|
-
rescue => error
|
42
|
-
if args[:raise_exception] == false
|
43
|
-
false
|
44
|
-
else
|
45
|
-
raise error
|
46
|
-
end
|
47
11
|
end
|
48
12
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
# If no action passed we should raise error if the user wants that.
|
53
|
-
# If not, just allow it.
|
54
|
-
if action.nil?
|
55
|
-
raise NoPolicyError.new "Policy method is missing" if Avo.configuration.raise_error_on_missing_policy
|
56
|
-
|
57
|
-
return true
|
58
|
-
end
|
59
|
-
|
60
|
-
# Add the question mark if it's missing
|
61
|
-
action = "#{action}?" unless action.end_with? "?"
|
62
|
-
authorize(user, record, action, policy_class: policy_class, **args)
|
63
|
-
end
|
64
|
-
|
65
|
-
def apply_policy(user, model, policy_class: nil)
|
66
|
-
return model if skip_authorization
|
67
|
-
|
68
|
-
client.apply_policy(user, model, policy_class: policy_class)
|
69
|
-
rescue NoPolicyError => error
|
70
|
-
return model unless Avo.configuration.raise_error_on_missing_policy
|
71
|
-
|
72
|
-
raise error
|
73
|
-
end
|
74
|
-
|
75
|
-
def skip_authorization
|
76
|
-
Avo::App.license.lacks_with_trial :authorization
|
77
|
-
end
|
78
|
-
|
79
|
-
def defined_methods(user, record, policy_class: nil, **args)
|
80
|
-
return client.policy!(user, record).methods if policy_class.nil?
|
81
|
-
|
82
|
-
# I'm aware this will not raise a Pundit error.
|
83
|
-
# Should the policy not exist, it will however raise an uninitialized constant error, which is probably what we want when specifying a custom policy
|
84
|
-
policy_class.new(user, record).methods
|
85
|
-
rescue NoPolicyError => error
|
86
|
-
return [] unless Avo.configuration.raise_error_on_missing_policy
|
87
|
-
|
88
|
-
raise error
|
89
|
-
rescue => error
|
90
|
-
if args[:raise_exception] == false
|
91
|
-
[]
|
92
|
-
else
|
93
|
-
raise error
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def pundit_client
|
98
|
-
raise Avo::MissingGemError.new("Please add `gem 'pundit'` to your Gemfile.") unless defined?(Pundit)
|
99
|
-
|
100
|
-
Avo::Services::AuthorizationClients::PunditClient
|
101
|
-
end
|
102
|
-
|
103
|
-
def nil_client
|
104
|
-
Avo::Services::AuthorizationClients::NilClient
|
13
|
+
def apply_policy(user, query)
|
14
|
+
query
|
105
15
|
end
|
106
16
|
end
|
107
17
|
|
108
18
|
def initialize(user = nil, record = nil, policy_class: nil)
|
109
19
|
@user = user
|
110
20
|
@record = record
|
111
|
-
@policy_class =
|
21
|
+
@policy_class = NilPolicy
|
112
22
|
end
|
113
23
|
|
114
24
|
def set_record(record)
|
@@ -117,28 +27,19 @@ module Avo
|
|
117
27
|
self
|
118
28
|
end
|
119
29
|
|
120
|
-
def
|
121
|
-
|
30
|
+
def apply_policy(query)
|
31
|
+
query
|
122
32
|
end
|
123
33
|
|
124
|
-
def
|
125
|
-
|
34
|
+
def authorize_action(*args)
|
35
|
+
true
|
126
36
|
end
|
127
37
|
|
128
|
-
def
|
129
|
-
|
38
|
+
def has_method?(*args, **kwargs)
|
39
|
+
false
|
130
40
|
end
|
131
41
|
|
132
|
-
|
133
|
-
method = "#{method}?" unless method.to_s.end_with? "?"
|
134
|
-
defined_methods(args[:record] || record, **args).include? method.to_sym
|
135
|
-
end
|
136
|
-
|
137
|
-
# Check the received method to see if the user overrode it in their config and then checks if it's present on the policy.
|
138
|
-
def has_action_method?(method, **args)
|
139
|
-
method = Avo.configuration.authorization_methods.stringify_keys[method.to_s] || method
|
140
|
-
|
141
|
-
has_method? method, **args
|
42
|
+
class NilPolicy
|
142
43
|
end
|
143
44
|
end
|
144
45
|
end
|