plutonium 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|