plutonium 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.standard.yml +4 -0
- data/.vscode/extensions.json +15 -0
- data/.vscode/launch.json +7 -0
- data/.vscode/settings.json +35 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README copy.md +84 -0
- data/README.md +67 -0
- data/Rakefile +8 -0
- data/app/views/layouts/resource.html.erb +43 -0
- data/app/views/resource/_color_modes.html.erb +55 -0
- data/app/views/resource/_details.html.erb +6 -0
- data/app/views/resource/_empty_card.html.erb +12 -0
- data/app/views/resource/_flash.html.erb +9 -0
- data/app/views/resource/_form.html.erb +32 -0
- data/app/views/resource/_header.html.erb +8 -0
- data/app/views/resource/_interactive_resource_action_form.html.erb +67 -0
- data/app/views/resource/_messages.html.erb +1 -0
- data/app/views/resource/_metric_card.html.erb +16 -0
- data/app/views/resource/_nav_user.html.erb +4 -0
- data/app/views/resource/_pagination.html.erb +6 -0
- data/app/views/resource/_pagy_pagination.html.erb +15 -0
- data/app/views/resource/_resource.html.erb +1 -0
- data/app/views/resource/_resource.rabl +5 -0
- data/app/views/resource/_sidebar.html.erb +11 -0
- data/app/views/resource/_sidebar_menu.html.erb +1 -0
- data/app/views/resource/_tab_menu.html.erb +13 -0
- data/app/views/resource/_table.html.erb +78 -0
- data/app/views/resource/_table_actions.html.erb +15 -0
- data/app/views/resource/_toast.html.erb +26 -0
- data/app/views/resource/_toolbar.html.erb +22 -0
- data/app/views/resource/_toolbar_actions.html.erb +16 -0
- data/app/views/resource/_toolbar_breadcrumbs.html.erb +32 -0
- data/app/views/resource/_toolbar_search_input.erb +27 -0
- data/app/views/resource/edit.html.erb +10 -0
- data/app/views/resource/errors.rabl +3 -0
- data/app/views/resource/index.html.erb +19 -0
- data/app/views/resource/index.rabl +3 -0
- data/app/views/resource/interactive_resource_collection_action.html.erb +11 -0
- data/app/views/resource/interactive_resource_record_action.html.erb +11 -0
- data/app/views/resource/interactive_resource_recordless_action.html.erb +11 -0
- data/app/views/resource/new.html.erb +11 -0
- data/app/views/resource/readme.md +16 -0
- data/app/views/resource/show.html.erb +14 -0
- data/app/views/resource/show.rabl +3 -0
- data/brakeman.ignore +51 -0
- data/lib/active_model/validations/array_validator.rb +74 -0
- data/lib/active_model/validations/attached_validator.rb +17 -0
- data/lib/active_model/validations/url_validator.rb +51 -0
- data/lib/generators/pu/core/install/install_generator.rb +43 -0
- data/lib/generators/pu/core/install/templates/.keep +0 -0
- data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/interactions/resource_interaction.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +5 -0
- data/lib/generators/pu/core/install/templates/app/policies/resource_policy.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +2 -0
- data/lib/generators/pu/core/install/templates/config/packages.rb +3 -0
- data/lib/generators/pu/gem/pagy/pagy_generator.rb +25 -0
- data/lib/generators/pu/gem/pagy/templates/.keep +0 -0
- data/lib/generators/pu/gem/pagy/templates/config/initializers/pagy.rb +4 -0
- data/lib/generators/pu/gem/rabl/rabl_generator.rb +25 -0
- data/lib/generators/pu/gem/rabl/templates/.keep +0 -0
- data/lib/generators/pu/gem/rabl/templates/config/initializers/rabl.rb +60 -0
- data/lib/generators/pu/gem/simple_form/simple_form_generator.rb +25 -0
- data/lib/generators/pu/gem/simple_form/templates/.keep +0 -0
- data/lib/generators/pu/gen/pug/pug_generator.rb +43 -0
- data/lib/generators/pu/gen/pug/templates/pug.rb.tt +23 -0
- data/lib/generators/pu/pkg/app/app_generator.rb +60 -0
- data/lib/generators/pu/pkg/app/templates/app/controllers/resource_controller.rb.tt +26 -0
- data/lib/generators/pu/pkg/app/templates/app/interactions/resource_interaction.rb.tt +4 -0
- data/lib/generators/pu/pkg/app/templates/app/policies/resource_policy.rb.tt +4 -0
- data/lib/generators/pu/pkg/app/templates/app/presenters/resource_presenter.rb.tt +4 -0
- data/lib/generators/pu/pkg/app/templates/config/routes.rb.tt +17 -0
- data/lib/generators/pu/pkg/app/templates/lib/engine.rb.tt +14 -0
- data/lib/generators/pu/pkg/feature/feature_generator.rb +44 -0
- data/lib/generators/pu/pkg/feature/templates/.keep +0 -0
- data/lib/generators/pu/pkg/feature/templates/app/controllers/resource_controller.rb.tt +7 -0
- data/lib/generators/pu/pkg/feature/templates/app/interactions/resource_interaction.rb.tt +4 -0
- data/lib/generators/pu/pkg/feature/templates/app/models/resource_record.rb.tt +5 -0
- data/lib/generators/pu/pkg/feature/templates/app/policies/resource_policy.rb.tt +4 -0
- data/lib/generators/pu/pkg/feature/templates/app/presenters/resource_presenter.rb.tt +4 -0
- data/lib/generators/pu/pkg/feature/templates/lib/engine.rb.tt +8 -0
- data/lib/generators/pu/resource/conn/conn_generator.rb +54 -0
- data/lib/generators/pu/resource/conn/templates/.keep +0 -0
- data/lib/generators/pu/resource/conn/templates/app/controllers/resource_controller.rb.tt +3 -0
- data/lib/generators/pu/resource/conn/templates/app/policies/resource_policy.rb.tt +3 -0
- data/lib/generators/pu/resource/conn/templates/app/presenters/resource_presenter.rb.tt +3 -0
- data/lib/generators/pu/resource/model/USAGE +113 -0
- data/lib/generators/pu/resource/model/model_generator.rb +163 -0
- data/lib/generators/pu/resource/model/templates/controller.rb.tt +5 -0
- data/lib/generators/pu/resource/model/templates/create_table_migration.rb.tt +26 -0
- data/lib/generators/pu/resource/model/templates/model.rb.tt +53 -0
- data/lib/generators/pu/resource/model/templates/module.rb.tt +7 -0
- data/lib/generators/pu/resource/model/templates/policy.rb.tt +4 -0
- data/lib/generators/pu/resource/model/templates/presenter.rb.tt +4 -0
- data/lib/generators/pu/resource/scaffold/scaffold_generator.rb +219 -0
- data/lib/generators/pu/resource/scaffold/templates/app/controllers/admin_resources/resource_controller.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/controllers/entity_resources/resource_controller.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/admin/resource_policy.rb.tt +22 -0
- data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/entity/resource_policy.rb.tt +22 -0
- data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/resource_policy.rb.tt +13 -0
- data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/admin_presenter.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/entity_presenter.rb.tt +7 -0
- data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/presenter.rb.tt +23 -0
- data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.html.erb.tt +3 -0
- data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.rabl +7 -0
- data/lib/generators/pu/rodauth/account_generator.rb +120 -0
- data/lib/generators/pu/rodauth/concerns/account_selector.rb +22 -0
- data/lib/generators/pu/rodauth/concerns/configuration.rb +211 -0
- data/lib/generators/pu/rodauth/concerns/feature_selector.rb +125 -0
- data/lib/generators/pu/rodauth/install_generator.rb +69 -0
- data/lib/generators/pu/rodauth/migration/active_record/account_expiration.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/active_sessions.erb +7 -0
- data/lib/generators/pu/rodauth/migration/active_record/audit_logging.erb +16 -0
- data/lib/generators/pu/rodauth/migration/active_record/base.erb +22 -0
- data/lib/generators/pu/rodauth/migration/active_record/disallow_password_reuse.erb +5 -0
- data/lib/generators/pu/rodauth/migration/active_record/email_auth.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/jwt_refresh.erb +7 -0
- data/lib/generators/pu/rodauth/migration/active_record/lockout.erb +13 -0
- data/lib/generators/pu/rodauth/migration/active_record/otp.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/password_expiration.erb +6 -0
- data/lib/generators/pu/rodauth/migration/active_record/recovery_codes.erb +6 -0
- data/lib/generators/pu/rodauth/migration/active_record/remember.erb +7 -0
- data/lib/generators/pu/rodauth/migration/active_record/reset_password.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/separate_passwords.erb +5 -0
- data/lib/generators/pu/rodauth/migration/active_record/single_session.erb +6 -0
- data/lib/generators/pu/rodauth/migration/active_record/sms_codes.erb +9 -0
- data/lib/generators/pu/rodauth/migration/active_record/verify_account.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/verify_login_change.erb +8 -0
- data/lib/generators/pu/rodauth/migration/active_record/webauthn.erb +13 -0
- data/lib/generators/pu/rodauth/migration/sequel/account_expiration.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/active_sessions.erb +8 -0
- data/lib/generators/pu/rodauth/migration/sequel/audit_logging.erb +17 -0
- data/lib/generators/pu/rodauth/migration/sequel/base.erb +25 -0
- data/lib/generators/pu/rodauth/migration/sequel/disallow_password_reuse.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/email_auth.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/jwt_refresh.erb +8 -0
- data/lib/generators/pu/rodauth/migration/sequel/lockout.erb +11 -0
- data/lib/generators/pu/rodauth/migration/sequel/otp.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/password_expiration.erb +5 -0
- data/lib/generators/pu/rodauth/migration/sequel/recovery_codes.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/remember.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/reset_password.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/separate_passwords.erb +6 -0
- data/lib/generators/pu/rodauth/migration/sequel/single_session.erb +5 -0
- data/lib/generators/pu/rodauth/migration/sequel/sms_codes.erb +8 -0
- data/lib/generators/pu/rodauth/migration/sequel/verify_account.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/verify_login_change.erb +7 -0
- data/lib/generators/pu/rodauth/migration/sequel/webauthn.erb +13 -0
- data/lib/generators/pu/rodauth/migration_generator.rb +190 -0
- data/lib/generators/pu/rodauth/templates/INSTRUCTIONS +52 -0
- data/lib/generators/pu/rodauth/templates/app/controllers/plugin_controller.rb.tt +6 -0
- data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +3 -0
- data/lib/generators/pu/rodauth/templates/app/mailers/account_mailer.rb.tt +4 -0
- data/lib/generators/pu/rodauth/templates/app/mailers/rodauth_mailer.rb.tt +62 -0
- data/lib/generators/pu/rodauth/templates/app/misc/account_rodauth_plugin.rb.tt +255 -0
- data/lib/generators/pu/rodauth/templates/app/misc/rodauth_app.rb.tt +24 -0
- data/lib/generators/pu/rodauth/templates/app/misc/rodauth_plugin.rb.tt +234 -0
- data/lib/generators/pu/rodauth/templates/app/models/account.rb.tt +40 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/_email_auth_request_form.html.erb +7 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form.html.erb +26 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form_footer.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/add_recovery_codes.html.erb +6 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_login.html.erb +27 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_password.html.erb +27 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/close_account.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/confirm_password.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/create_account.html.erb +35 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/email_auth.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/login.html.erb +4 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/logout.html.erb +14 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/multi_phase_login.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_auth.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_disable.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_setup.html.erb +41 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_auth.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_codes.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/remember.html.erb +22 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password.html.erb +19 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password_request.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_auth.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_confirm.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_disable.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_request.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_setup.html.erb +23 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_email_auth_request_form.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form.html.erb +24 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form_footer.html.erb +7 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/add_recovery_codes.html.erb +16 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_login.html.erb +25 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_password.html.erb +25 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/close_account.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/confirm_password.html.erb +19 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/create_account.html.erb +33 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/email_auth.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/login.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/logout.html.erb +10 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/multi_phase_login.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_auth.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_disable.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_setup.html.erb +32 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_auth.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_codes.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/remember.html.erb +18 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password_request.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_auth.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_confirm.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_disable.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_request.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_setup.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_auth.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_disable.html.erb +11 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_manage.html.erb +26 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account_request.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account.html.erb +19 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account_resend.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_login_change.html.erb +3 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_auth.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_autofill.html.erb +10 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_remove.html.erb +21 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_setup.html.erb +21 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_auth.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_disable.html.erb +13 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_manage.html.erb +22 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account_request.html.erb +9 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account.html.erb +21 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account_resend.html.erb +17 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_login_change.html.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_auth.html.erb +15 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_autofill.html.erb +10 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_remove.html.erb +23 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_setup.html.erb +23 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/email_auth.text.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/password_changed.text.erb +2 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password.text.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password_notify.text.erb +2 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb +5 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_account.text.erb +4 -0
- data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_login_change.text.erb +10 -0
- data/lib/generators/pu/rodauth/templates/config/initializers/rodauth.rb.tt +3 -0
- data/lib/generators/pu/rodauth/templates/db/migrate/create_rodauth.rb.tt +13 -0
- data/lib/generators/pu/rodauth/views_generator.rb +125 -0
- data/lib/plutonium/auth/public_access.rb +17 -0
- data/lib/plutonium/auth/rodauth.rb +35 -0
- data/lib/plutonium/auth.rb +12 -0
- data/lib/plutonium/config.rb +11 -0
- data/lib/plutonium/core/.DS_Store +0 -0
- data/lib/plutonium/core/action.rb +46 -0
- data/lib/plutonium/core/actions/basic_action.rb +16 -0
- data/lib/plutonium/core/actions/collection.rb +33 -0
- data/lib/plutonium/core/actions/destroy_action.rb +21 -0
- data/lib/plutonium/core/actions/edit_action.rb +19 -0
- data/lib/plutonium/core/actions/interactive_action.rb +64 -0
- data/lib/plutonium/core/actions/new_action.rb +18 -0
- data/lib/plutonium/core/actions/show_action.rb +17 -0
- data/lib/plutonium/core/actions.rb +17 -0
- data/lib/plutonium/core/app_controller.rb +121 -0
- data/lib/plutonium/core/autodiscovery/discoverer.rb +15 -0
- data/lib/plutonium/core/autodiscovery/input_discoverer.rb +33 -0
- data/lib/plutonium/core/autodiscovery/renderer_discoverer.rb +33 -0
- data/lib/plutonium/core/autodiscovery.rb +13 -0
- data/lib/plutonium/core/controllers/authorizable.rb +56 -0
- data/lib/plutonium/core/controllers/bootable.rb +44 -0
- data/lib/plutonium/core/controllers/crud_actions.rb +128 -0
- data/lib/plutonium/core/controllers/entity_scoping.rb +69 -0
- data/lib/plutonium/core/controllers/interactive_actions.rb +210 -0
- data/lib/plutonium/core/controllers/presentable.rb +59 -0
- data/lib/plutonium/core/controllers.rb +16 -0
- data/lib/plutonium/core/definers/action_definer.rb +25 -0
- data/lib/plutonium/core/definers/field_definer.rb +19 -0
- data/lib/plutonium/core/definers/input_definer.rb +37 -0
- data/lib/plutonium/core/definers/renderer_definer.rb +35 -0
- data/lib/plutonium/core/definers.rb +14 -0
- data/lib/plutonium/core/fields/inputs/association_input.rb +26 -0
- data/lib/plutonium/core/fields/inputs/basic_input.rb +42 -0
- data/lib/plutonium/core/fields/inputs/belongs_to_input.rb +15 -0
- data/lib/plutonium/core/fields/inputs/factory.rb +58 -0
- data/lib/plutonium/core/fields/inputs/has_many_input.rb +15 -0
- data/lib/plutonium/core/fields/inputs/noop_input.rb +19 -0
- data/lib/plutonium/core/fields/inputs.rb +18 -0
- data/lib/plutonium/core/fields/renderers/association_renderer.rb +25 -0
- data/lib/plutonium/core/fields/renderers/basic_renderer.rb +27 -0
- data/lib/plutonium/core/fields/renderers/factory.rb +52 -0
- data/lib/plutonium/core/fields/renderers.rb +15 -0
- data/lib/plutonium/core/fields.rb +12 -0
- data/lib/plutonium/core/ui/collection.rb +14 -0
- data/lib/plutonium/core/ui/detail.rb +11 -0
- data/lib/plutonium/core/ui/form.rb +11 -0
- data/lib/plutonium/core/ui.rb +13 -0
- data/lib/plutonium/core.rb +16 -0
- data/lib/plutonium/helpers/action_buttons_helper.rb +32 -0
- data/lib/plutonium/helpers/application_helper.rb +22 -0
- data/lib/plutonium/helpers/attachment_helper.rb +62 -0
- data/lib/plutonium/helpers/content_helper.rb +66 -0
- data/lib/plutonium/helpers/display_helper.rb +83 -0
- data/lib/plutonium/helpers/form_helper.rb +24 -0
- data/lib/plutonium/helpers/menu_helper.rb +69 -0
- data/lib/plutonium/helpers/pagination_helper.rb +9 -0
- data/lib/plutonium/helpers/turbo_helper.rb +13 -0
- data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +9 -0
- data/lib/plutonium/helpers.rb +31 -0
- data/lib/plutonium/initializers/TODO +2 -0
- data/lib/plutonium/initializers/pagy.rb +5 -0
- data/lib/plutonium/initializers/patches.rb +2 -0
- data/lib/plutonium/initializers/rabl.rb +60 -0
- data/lib/plutonium/initializers/simple_form.rb +405 -0
- data/lib/plutonium/lib/after_commit.rb +34 -0
- data/lib/plutonium/lib/bit_flags.rb +36 -0
- data/lib/plutonium/packaging/app.rb +125 -0
- data/lib/plutonium/packaging/feature.rb +18 -0
- data/lib/plutonium/packaging/package.rb +22 -0
- data/lib/plutonium/packaging.rb +9 -0
- data/lib/plutonium/policy/initializer.rb +22 -0
- data/lib/plutonium/policy/scope.rb +19 -0
- data/lib/plutonium/policy.rb +8 -0
- data/lib/plutonium/preserved__/field.rb +65 -0
- data/lib/plutonium/preserved__/input.rb +93 -0
- data/lib/plutonium/reactor/core.rb +61 -0
- data/lib/plutonium/reactor/resource_context.rb +15 -0
- data/lib/plutonium/reactor/resource_controller.rb +108 -0
- data/lib/plutonium/reactor/resource_interaction.rb +8 -0
- data/lib/plutonium/reactor/resource_policy.rb +105 -0
- data/lib/plutonium/reactor/resource_presenter.rb +42 -0
- data/lib/plutonium/reactor/resource_record.rb +123 -0
- data/lib/plutonium/reactor.rb +13 -0
- data/lib/plutonium/refinements/parameter_refinements.rb +26 -0
- data/lib/plutonium/simple_form_components/attachment_component.rb +77 -0
- data/lib/plutonium/simple_form_components/input_group_component.rb +14 -0
- data/lib/plutonium/version.rb +3 -0
- data/lib/plutonium.rb +31 -0
- data/plutonium.gemspec +47 -0
- data/public/.keep +0 -0
- data/public/plutonium-assets/application.css +24280 -0
- data/public/plutonium-assets/application.js +31420 -0
- data/public/plutonium-assets/fonts/bootstrap-icons.woff +0 -0
- data/public/plutonium-assets/fonts/bootstrap-icons.woff2 +0 -0
- data/public/plutonium-assets/logo.png +0 -0
- data/sig/plutonium.rbs +4 -0
- metadata +519 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Autodiscovery
|
4
|
+
module InputDiscoverer
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Discoverer
|
7
|
+
|
8
|
+
class_methods do
|
9
|
+
private
|
10
|
+
|
11
|
+
def autodiscovery_input_cache = @autodiscovery_input_cache ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# If cache_discovery is enabled, use the class level cache that persists
|
17
|
+
# between requests, otherwise use the instance one.
|
18
|
+
def autodiscovery_input_cache
|
19
|
+
if Plutonium::Config.cache_discovery
|
20
|
+
self.class.autodiscovery_input_cache
|
21
|
+
else
|
22
|
+
@autodiscovery_input_cache ||= {}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def autodiscover_input(name)
|
27
|
+
autodiscovery_input_cache[name] ||=
|
28
|
+
Plutonium::Core::Fields::Inputs::Factory.for_resource_attribute(resource_class, name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Autodiscovery
|
4
|
+
module RendererDiscoverer
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Discoverer
|
7
|
+
|
8
|
+
class_methods do
|
9
|
+
private
|
10
|
+
|
11
|
+
def autodiscovery_renderer_cache = @autodiscovery_renderer_cache ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# If cache_discovery is enabled, use the class level cache that persists
|
17
|
+
# between requests, otherwise use the instance one.
|
18
|
+
def autodiscovery_renderer_cache
|
19
|
+
if Plutonium::Config.cache_discovery
|
20
|
+
self.class.autodiscovery_renderer_cache
|
21
|
+
else
|
22
|
+
@autodiscovery_renderer_cache ||= {}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def autodiscover_renderer(name)
|
27
|
+
autodiscovery_renderer_cache[name] ||=
|
28
|
+
Plutonium::Core::Fields::Renderers::Factory.for_resource_attribute(resource_class, name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "pundit"
|
2
|
+
|
3
|
+
module Plutonium
|
4
|
+
module Core
|
5
|
+
module Controllers
|
6
|
+
module Authorizable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include Pundit::Authorization
|
9
|
+
|
10
|
+
included do
|
11
|
+
after_action :verify_authorized
|
12
|
+
after_action :verify_policy_scoped, except: %i[new create]
|
13
|
+
|
14
|
+
helper_method :permitted_attributes
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def policy_namespace(scope)
|
20
|
+
raise NotImplementedError, "policy_namespace"
|
21
|
+
end
|
22
|
+
|
23
|
+
def pundit_user
|
24
|
+
resource_context
|
25
|
+
end
|
26
|
+
|
27
|
+
def policy(scope)
|
28
|
+
super(policy_namespace(scope))
|
29
|
+
end
|
30
|
+
|
31
|
+
def policy_scope(scope)
|
32
|
+
super(policy_namespace(scope))
|
33
|
+
end
|
34
|
+
|
35
|
+
def authorize(record, query = nil)
|
36
|
+
super(policy_namespace(record), query)
|
37
|
+
end
|
38
|
+
|
39
|
+
def permitted_attributes
|
40
|
+
@permitted_attributes ||= current_policy.send :"permitted_attributes_for_#{action_name}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def current_policy
|
44
|
+
@current_policy ||= begin
|
45
|
+
policy_subject = resource_record || resource_class
|
46
|
+
policy(policy_subject)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parent_policy
|
51
|
+
@parent_policy ||= policy(current_parent) if current_parent.present?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Controllers
|
4
|
+
module Bootable
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :package
|
9
|
+
class_attribute :resource_class, instance_writer: false, instance_predicate: false
|
10
|
+
|
11
|
+
helper_method :resource_class
|
12
|
+
end
|
13
|
+
|
14
|
+
class_methods do
|
15
|
+
def current_engine
|
16
|
+
"#{package}::Engine".constantize
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def boot(package)
|
22
|
+
self.package = package
|
23
|
+
|
24
|
+
prepend_view_path current_engine.paths["app/views"].first
|
25
|
+
end
|
26
|
+
|
27
|
+
def controller_for(resource_class)
|
28
|
+
self.resource_class = resource_class
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def current_engine
|
35
|
+
@current_engine ||= self.class.current_engine
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_package
|
39
|
+
self.class.package
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Controllers
|
4
|
+
module CrudActions
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
# GET /resources(.{format})
|
8
|
+
def index
|
9
|
+
authorize resource_class
|
10
|
+
|
11
|
+
@ransack = policy_scope(resource_class).ransack(params[:q])
|
12
|
+
@pagy, @resource_records = pagy @ransack.result
|
13
|
+
@collection = build_collection
|
14
|
+
|
15
|
+
render :index
|
16
|
+
end
|
17
|
+
|
18
|
+
# GET /resources/1(.{format})
|
19
|
+
def show
|
20
|
+
authorize resource_record
|
21
|
+
|
22
|
+
@detail = build_detail
|
23
|
+
|
24
|
+
render :show
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET /resources/new
|
28
|
+
def new
|
29
|
+
authorize resource_class
|
30
|
+
|
31
|
+
@resource_record = resource_class.new
|
32
|
+
# set params if they have been passed
|
33
|
+
resource_record.attributes = params[resource_param_key].present? ? resource_params : {}
|
34
|
+
@form = build_form
|
35
|
+
|
36
|
+
render :new
|
37
|
+
end
|
38
|
+
|
39
|
+
# GET /resources/1/edit
|
40
|
+
def edit
|
41
|
+
authorize resource_record
|
42
|
+
|
43
|
+
# set params if they have been passed
|
44
|
+
resource_record.attributes = params[resource_param_key].present? ? resource_params : {}
|
45
|
+
@form = build_form
|
46
|
+
|
47
|
+
render :edit
|
48
|
+
end
|
49
|
+
|
50
|
+
# POST /resources(.{format})
|
51
|
+
def create
|
52
|
+
authorize resource_class
|
53
|
+
|
54
|
+
@resource_record = resource_class.new resource_params
|
55
|
+
|
56
|
+
respond_to do |format|
|
57
|
+
if resource_record.save
|
58
|
+
format.html do
|
59
|
+
redirect_to adapt_route_args(resource_record),
|
60
|
+
notice: "#{resource_class.model_name.human} was successfully created."
|
61
|
+
end
|
62
|
+
format.any { render :show, status: :created, location: adapt_route_args(resource_record) }
|
63
|
+
else
|
64
|
+
format.html do
|
65
|
+
@form = build_form
|
66
|
+
render :new, status: :unprocessable_entity
|
67
|
+
end
|
68
|
+
format.any do
|
69
|
+
@errors = resource_record.errors
|
70
|
+
render "errors", status: :unprocessable_entity
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# PATCH/PUT /resources/1(.{format})
|
77
|
+
def update
|
78
|
+
authorize resource_record
|
79
|
+
|
80
|
+
respond_to do |format|
|
81
|
+
if resource_record.update(resource_params)
|
82
|
+
format.html do
|
83
|
+
redirect_to adapt_route_args(resource_record), notice: "#{resource_class.model_name.human} was successfully updated.",
|
84
|
+
status: :see_other
|
85
|
+
end
|
86
|
+
format.any { render :show, status: :ok, location: adapt_route_args(resource_record) }
|
87
|
+
else
|
88
|
+
format.html do
|
89
|
+
@form = build_form
|
90
|
+
render :edit, status: :unprocessable_entity
|
91
|
+
end
|
92
|
+
format.any do
|
93
|
+
@errors = resource_record.errors
|
94
|
+
render "errors", status: :unprocessable_entity
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# DELETE /resources/1(.{format})
|
101
|
+
def destroy
|
102
|
+
authorize resource_record
|
103
|
+
|
104
|
+
respond_to do |format|
|
105
|
+
resource_record.destroy
|
106
|
+
|
107
|
+
format.html do
|
108
|
+
redirect_to adapt_route_args(resource_class),
|
109
|
+
notice: "#{resource_class.model_name.human} was successfully deleted."
|
110
|
+
end
|
111
|
+
format.json { head :no_content }
|
112
|
+
rescue ActiveRecord::InvalidForeignKey
|
113
|
+
format.html do
|
114
|
+
redirect_to adapt_route_args(resource_record),
|
115
|
+
alert: "#{resource_class.model_name.human} is referenced by other records."
|
116
|
+
end
|
117
|
+
format.any do
|
118
|
+
@errors = ActiveModel::Errors.new resource_record
|
119
|
+
@errors.add :base, :existing_references, message: "is referenced by other records"
|
120
|
+
|
121
|
+
render "errors", status: :unprocessable_entity
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Controllers
|
4
|
+
module EntityScoping
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :remember_scoped_entity
|
9
|
+
helper_method :current_scoped_entity
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def scoped_to_entity?
|
15
|
+
current_engine.scoped_to_entity?
|
16
|
+
end
|
17
|
+
|
18
|
+
def scoped_entity_class
|
19
|
+
ensure_legal_entity_scoping_method_access! :scoped_entity_class
|
20
|
+
|
21
|
+
current_engine.scoped_entity_class
|
22
|
+
end
|
23
|
+
|
24
|
+
def scoped_entity_param_key
|
25
|
+
ensure_legal_entity_scoping_method_access! :scoped_entity_param_key
|
26
|
+
|
27
|
+
current_engine.scoped_entity_param_key
|
28
|
+
end
|
29
|
+
|
30
|
+
def scoped_entity_session_key
|
31
|
+
ensure_legal_entity_scoping_method_access! :scoped_entity_session_key
|
32
|
+
|
33
|
+
:scoped_entity_id
|
34
|
+
end
|
35
|
+
|
36
|
+
def current_scoped_entity
|
37
|
+
ensure_legal_entity_scoping_method_access! :current_scoped_entity
|
38
|
+
|
39
|
+
return unless current_user.present?
|
40
|
+
|
41
|
+
@current_scoped_entity ||= scoped_entity_class
|
42
|
+
.associated_with(current_user)
|
43
|
+
.from_path_param(request.path_parameters[scoped_entity_param_key])
|
44
|
+
.first! # Raise NotFound if user does not have access to the entity or it does not exist
|
45
|
+
end
|
46
|
+
|
47
|
+
def remember_scoped_entity
|
48
|
+
return unless scoped_to_entity?
|
49
|
+
|
50
|
+
session[scoped_entity_session_key] = current_scoped_entity.to_global_id.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def remembered_scoped_entity
|
54
|
+
ensure_legal_entity_scoping_method_access! :remembered_scoped_entity
|
55
|
+
|
56
|
+
@remembered_scoped_entity ||= GlobalID::Locator.locate session[scoped_entity_session_key]
|
57
|
+
end
|
58
|
+
|
59
|
+
def ensure_legal_entity_scoping_method_access!(method)
|
60
|
+
return if scoped_to_entity?
|
61
|
+
|
62
|
+
raise NotImplementedError, "this request is not scoped to an entity\n\n" \
|
63
|
+
"add the `scope_to_entity YourEntityRecord` directive in " \
|
64
|
+
"#{current_engine} or implement #{self.class}##{method}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Controllers
|
4
|
+
module InteractiveActions
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :validate_interactive_resource_action, only: %i[
|
9
|
+
begin_interactive_resource_record_action commit_interactive_resource_record_action
|
10
|
+
begin_interactive_resource_collection_action commit_interactive_resource_collection_action
|
11
|
+
begin_interactive_resource_recordless_action commit_interactive_resource_recordless_action
|
12
|
+
]
|
13
|
+
|
14
|
+
before_action :authorize_interactive_resource_record_action, only: %i[
|
15
|
+
begin_interactive_resource_record_action commit_interactive_resource_record_action
|
16
|
+
]
|
17
|
+
|
18
|
+
before_action :authorize_interactive_resource_action, only: %i[
|
19
|
+
begin_interactive_resource_collection_action commit_interactive_resource_collection_action
|
20
|
+
begin_interactive_resource_recordless_action commit_interactive_resource_recordless_action
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /resources/1/actions/:interactive_action
|
25
|
+
def begin_interactive_resource_record_action
|
26
|
+
@interaction = current_interactive_action.interaction.new interaction_params
|
27
|
+
|
28
|
+
if helpers.current_turbo_frame == "modal"
|
29
|
+
render layout: false
|
30
|
+
else
|
31
|
+
render :interactive_resource_record_action
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# POST /resources/1/actions/:interactive_action
|
36
|
+
def commit_interactive_resource_record_action
|
37
|
+
respond_to do |format|
|
38
|
+
inputs = interaction_params.merge(resource: resource_record)
|
39
|
+
@interaction = current_interactive_action.interaction.run(inputs)
|
40
|
+
|
41
|
+
if @interaction.valid?
|
42
|
+
flash[:notice] = "TODO:#{current_interactive_action} was successfully updated."
|
43
|
+
|
44
|
+
format.html { redirect_to adapt_route_args(@interaction.result), status: :see_other }
|
45
|
+
format.any { render :show, status: :ok, location: adapt_route_args(@interaction.result) }
|
46
|
+
|
47
|
+
if helpers.current_turbo_frame == "modal"
|
48
|
+
format.turbo_stream do
|
49
|
+
render turbo_stream: [
|
50
|
+
turbo_stream.redirect(url_for(adapt_route_args(@interaction.result)))
|
51
|
+
]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
else
|
55
|
+
format.html do
|
56
|
+
render :interactive_resource_record_action, status: :unprocessable_entity
|
57
|
+
end
|
58
|
+
format.any do
|
59
|
+
@errors = @interaction.errors
|
60
|
+
render "errors", status: :unprocessable_entity
|
61
|
+
end
|
62
|
+
|
63
|
+
if helpers.current_turbo_frame == "modal"
|
64
|
+
format.turbo_stream do
|
65
|
+
render turbo_stream: turbo_stream.replace(:modal, partial: "interactive_resource_record_action_form")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# GET /resources/actions/:interactive_action?ids[]=1&ids[]=2
|
73
|
+
def begin_interactive_resource_collection_action
|
74
|
+
# TODO: ensure that the selected list matches the returned value
|
75
|
+
interactive_resource_collection
|
76
|
+
@interaction = current_interactive_action.interaction.new((params[:interaction] || {}).except(:resources))
|
77
|
+
|
78
|
+
if helpers.current_turbo_frame == "modal"
|
79
|
+
render layout: false
|
80
|
+
else
|
81
|
+
render :interactive_resource_collection_action
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# POST /resources/actions/:interactive_action?ids[]=1&ids[]=2
|
86
|
+
def commit_interactive_resource_collection_action
|
87
|
+
respond_to do |format|
|
88
|
+
inputs = interaction_params.merge(resources: interactive_resource_collection)
|
89
|
+
@interaction = current_interactive_action.interaction.run(inputs)
|
90
|
+
|
91
|
+
if @interaction.valid?
|
92
|
+
collection_count = interactive_resource_collection.size
|
93
|
+
|
94
|
+
flash[:notice] = "TODO:#{current_interactive_action} #{collection_count} #{resource_class.model_name.human.pluralize(collection_count)} successfully updated."
|
95
|
+
|
96
|
+
format.html { redirect_to adapt_route_args(resource_class) }
|
97
|
+
if helpers.current_turbo_frame == "modal"
|
98
|
+
format.turbo_stream do
|
99
|
+
render turbo_stream: [
|
100
|
+
turbo_stream.redirect(url_for(resource_class))
|
101
|
+
]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
else
|
105
|
+
format.html do
|
106
|
+
render :interactive_resource_collection_action, status: :unprocessable_entity
|
107
|
+
end
|
108
|
+
format.any do
|
109
|
+
@errors = @interaction.errors
|
110
|
+
render "errors", status: :unprocessable_entity
|
111
|
+
end
|
112
|
+
|
113
|
+
if helpers.current_turbo_frame == "modal"
|
114
|
+
format.turbo_stream do
|
115
|
+
render turbo_stream: turbo_stream.replace(:modal, partial: "interactive_resource_collection_action_form")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# GET /resources/actions/:interactive_action
|
123
|
+
def begin_interactive_resource_recordless_action
|
124
|
+
skip_policy_scope
|
125
|
+
|
126
|
+
@interaction = current_interactive_action.interaction.new interaction_params
|
127
|
+
|
128
|
+
if helpers.current_turbo_frame == "modal"
|
129
|
+
render layout: false
|
130
|
+
else
|
131
|
+
render :interactive_resource_recordless_action
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# POST /resources/actions/:interactive_action
|
136
|
+
def commit_interactive_resource_recordless_action
|
137
|
+
skip_policy_scope
|
138
|
+
|
139
|
+
respond_to do |format|
|
140
|
+
inputs = interaction_params
|
141
|
+
@interaction = current_interactive_action.interaction.run(inputs)
|
142
|
+
|
143
|
+
if @interaction.valid?
|
144
|
+
flash[:notice] = "TODO:#{current_interactive_action} was successfully updated."
|
145
|
+
|
146
|
+
format.html { redirect_to adapt_route_args(resource_class) }
|
147
|
+
|
148
|
+
if helpers.current_turbo_frame == "modal"
|
149
|
+
format.turbo_stream do
|
150
|
+
render turbo_stream: [
|
151
|
+
turbo_stream.redirect(url_for(adapt_route_args(resource_class)))
|
152
|
+
]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
else
|
156
|
+
format.html do
|
157
|
+
render :interactive_resource_recordless_action, status: :unprocessable_entity
|
158
|
+
end
|
159
|
+
format.any do
|
160
|
+
@errors = @interaction.errors
|
161
|
+
render "errors", status: :unprocessable_entity
|
162
|
+
end
|
163
|
+
|
164
|
+
if helpers.current_turbo_frame == "modal"
|
165
|
+
format.turbo_stream do
|
166
|
+
render turbo_stream: turbo_stream.replace(:modal, partial: "interactive_resource_recordless_action_form")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def current_interactive_action
|
176
|
+
@current_interactive_action = interactive_resource_actions[params[:interactive_action].to_sym]
|
177
|
+
end
|
178
|
+
|
179
|
+
def interactive_resource_actions
|
180
|
+
@interactive_resource_actions ||= current_presenter.actions.except :new, :show, :edit, :destroy
|
181
|
+
end
|
182
|
+
|
183
|
+
def validate_interactive_resource_action
|
184
|
+
interactive_resource_action = params[:interactive_action]&.to_sym
|
185
|
+
unless interactive_resource_actions.key?(interactive_resource_action)
|
186
|
+
raise ::AbstractController::ActionNotFound, "Unknown action '#{interactive_resource_action}'"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def authorize_interactive_resource_record_action
|
191
|
+
interactive_resource_action = params[:interactive_action]&.to_sym
|
192
|
+
authorize resource_record, :"#{interactive_resource_action}?"
|
193
|
+
end
|
194
|
+
|
195
|
+
def authorize_interactive_resource_action
|
196
|
+
interactive_resource_action = params[:interactive_action]&.to_sym
|
197
|
+
authorize resource_class, :"#{interactive_resource_action}?"
|
198
|
+
end
|
199
|
+
|
200
|
+
def interactive_resource_collection
|
201
|
+
@interactive_resource_collection ||= policy_scope(resource_class).from_path_param(params.require(:ids)).all
|
202
|
+
end
|
203
|
+
|
204
|
+
def interaction_params
|
205
|
+
(params[:interaction] || {}).except(:resource, :resources)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Controllers
|
4
|
+
module Presentable
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :presentable_attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def resource_presenter(resource_class)
|
14
|
+
raise NotImplementedError, "#{self.class}#resource_presenter"
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_presenter
|
18
|
+
resource_presenter resource_class
|
19
|
+
end
|
20
|
+
|
21
|
+
def presentable_attributes
|
22
|
+
@presentable_attributes ||= begin
|
23
|
+
presentable_attributes = permitted_attributes
|
24
|
+
presentable_attributes -= [scoped_entity_param_key, :"#{scoped_entity_param_key}_id"] if scoped_to_entity?
|
25
|
+
presentable_attributes -= [parent_input_param, :"#{parent_input_param}_id"] if current_parent.present?
|
26
|
+
presentable_attributes
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_collection
|
31
|
+
Plutonium::Core::UI::Collection.new(
|
32
|
+
resource_class:,
|
33
|
+
records: @resource_records,
|
34
|
+
fields: current_presenter.defined_renderers_for(presentable_attributes),
|
35
|
+
actions: current_presenter.actions,
|
36
|
+
pagination: @pagy,
|
37
|
+
search_object: @ransack
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_detail
|
42
|
+
Plutonium::Core::UI::Detail.new(
|
43
|
+
resource_class:,
|
44
|
+
record: resource_record,
|
45
|
+
fields: current_presenter.defined_renderers_for(presentable_attributes),
|
46
|
+
actions: current_presenter.actions
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_form
|
51
|
+
Plutonium::Core::UI::Form.new(
|
52
|
+
record: resource_record,
|
53
|
+
inputs: current_presenter.defined_inputs_for(presentable_attributes)
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Controllers
|
4
|
+
extend ActiveSupport::Autoload
|
5
|
+
|
6
|
+
eager_autoload do
|
7
|
+
autoload :Authorizable
|
8
|
+
autoload :Bootable
|
9
|
+
autoload :CrudActions
|
10
|
+
autoload :EntityScoping
|
11
|
+
autoload :Presentable
|
12
|
+
autoload :InteractiveActions
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Core
|
3
|
+
module Definers
|
4
|
+
module ActionDefiner
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def actions
|
8
|
+
action_definitions
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def action_definitions = @action_definitions ||= Plutonium::Core::Actions::Collection.new
|
14
|
+
|
15
|
+
def define_action(action)
|
16
|
+
action_definitions[action.name] = action
|
17
|
+
end
|
18
|
+
|
19
|
+
def action_defined?(name)
|
20
|
+
action_definitions.key? name
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|