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,405 @@
|
|
1
|
+
require "simple_form"
|
2
|
+
|
3
|
+
# Register components
|
4
|
+
Dir[Plutonium.lib_root.join("simple_form_components", "*.rb")].each { |component| require component }
|
5
|
+
|
6
|
+
# Use this setup block to configure all options available in SimpleForm.
|
7
|
+
SimpleForm.setup do |config|
|
8
|
+
# Tell browsers whether to use the native HTML5 validations (novalidate form option).
|
9
|
+
config.browser_validations = true
|
10
|
+
|
11
|
+
# Custom mappings for input types. This should be a hash containing a regexp
|
12
|
+
|
13
|
+
# Disable country select
|
14
|
+
config.input_mappings = {/country/ => :select}
|
15
|
+
|
16
|
+
# Default class for buttons
|
17
|
+
config.button_class = "btn"
|
18
|
+
|
19
|
+
# Define the default class of the input wrapper of the boolean input.
|
20
|
+
config.boolean_label_class = "form-check-label"
|
21
|
+
|
22
|
+
# How the label text should be generated altogether with the required text.
|
23
|
+
config.label_text = ->(label, required, _explicit_label) { "#{label} #{required}" }
|
24
|
+
|
25
|
+
# Define the way to render check boxes / radio buttons with labels.
|
26
|
+
config.boolean_style = :inline
|
27
|
+
|
28
|
+
# You can wrap each item in a collection of radio/check boxes with a tag
|
29
|
+
config.item_wrapper_tag = :div
|
30
|
+
|
31
|
+
# Defines if the default input wrapper class should be included in radio
|
32
|
+
# collection wrappers.
|
33
|
+
config.include_default_input_wrapper_class = false
|
34
|
+
|
35
|
+
# CSS class to add for error notification helper.
|
36
|
+
config.error_notification_class = "alert alert-danger"
|
37
|
+
|
38
|
+
# Method used to tidy up errors. Specify any Rails Array method.
|
39
|
+
# :first lists the first message for each field.
|
40
|
+
# :to_sentence to list all errors for each field.
|
41
|
+
config.error_method = :to_sentence
|
42
|
+
|
43
|
+
# add validation classes to `input_field`
|
44
|
+
config.input_field_error_class = "is-invalid"
|
45
|
+
config.input_field_valid_class = "is-valid"
|
46
|
+
|
47
|
+
# vertical forms
|
48
|
+
#
|
49
|
+
# vertical default_wrapper
|
50
|
+
config.wrappers :vertical_form, class: "mb-3" do |b|
|
51
|
+
b.use :html5
|
52
|
+
b.use :placeholder
|
53
|
+
b.use :maxlength
|
54
|
+
b.use :minlength
|
55
|
+
b.optional :pattern
|
56
|
+
b.use :min_max
|
57
|
+
b.optional :readonly
|
58
|
+
b.use :label, class: "form-label"
|
59
|
+
b.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid"
|
60
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback"}
|
61
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
62
|
+
end
|
63
|
+
|
64
|
+
# vertical input for boolean
|
65
|
+
config.wrappers :vertical_boolean, tag: "fieldset", class: "mb-3" do |b|
|
66
|
+
b.use :html5
|
67
|
+
b.optional :readonly
|
68
|
+
b.wrapper :form_check_wrapper, class: "form-check" do |bb|
|
69
|
+
bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
70
|
+
bb.use :label, class: "form-check-label"
|
71
|
+
bb.use :full_error, wrap_with: {class: "invalid-feedback"}
|
72
|
+
bb.use :hint, wrap_with: {class: "form-text"}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# vertical input for radio buttons and check boxes
|
77
|
+
config.wrappers :vertical_collection, item_wrapper_class: "form-check", item_label_class: "form-check-label",
|
78
|
+
tag: "fieldset", class: "mb-3" do |b|
|
79
|
+
b.use :html5
|
80
|
+
b.optional :readonly
|
81
|
+
b.use :label, class: "form-label"
|
82
|
+
b.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
83
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback d-block"}
|
84
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
85
|
+
end
|
86
|
+
|
87
|
+
# vertical input for inline radio buttons and check boxes
|
88
|
+
config.wrappers :vertical_collection_inline, item_wrapper_class: "form-check form-check-inline",
|
89
|
+
item_label_class: "form-check-label", tag: "fieldset", class: "mb-3" do |b|
|
90
|
+
b.use :html5
|
91
|
+
b.optional :readonly
|
92
|
+
b.wrapper :legend_tag, tag: "legend", class: "col-form-label pt-0" do |ba|
|
93
|
+
ba.use :label_text
|
94
|
+
end
|
95
|
+
b.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
96
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback d-block"}
|
97
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
98
|
+
end
|
99
|
+
|
100
|
+
# vertical file input
|
101
|
+
config.wrappers :vertical_file, class: "mb-3" do |b|
|
102
|
+
b.use :html5
|
103
|
+
b.use :placeholder
|
104
|
+
b.optional :maxlength
|
105
|
+
b.optional :minlength
|
106
|
+
b.optional :readonly
|
107
|
+
b.use :label, class: "form-label"
|
108
|
+
b.wrapper tag: "div", html: {style: "display: flex; flex-direction: column-reverse;"} do |ba|
|
109
|
+
ba.optional :attachment
|
110
|
+
ba.wrapper tag: "div" do |bc|
|
111
|
+
bc.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid"
|
112
|
+
bc.use :full_error, wrap_with: {class: "invalid-feedback"}
|
113
|
+
bc.use :hint, wrap_with: {class: "form-text"}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# vertical select input
|
119
|
+
config.wrappers :vertical_select, class: "mb-3" do |b|
|
120
|
+
b.use :html5
|
121
|
+
b.optional :readonly
|
122
|
+
b.use :label, class: "form-label"
|
123
|
+
b.use :input, class: "form-select", error_class: "is-invalid", valid_class: "is-valid"
|
124
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback"}
|
125
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
126
|
+
end
|
127
|
+
|
128
|
+
# vertical multi select
|
129
|
+
config.wrappers :vertical_multi_select, class: "mb-3" do |b|
|
130
|
+
b.use :html5
|
131
|
+
b.optional :readonly
|
132
|
+
b.use :label, class: "form-label"
|
133
|
+
b.wrapper class: "d-flex flex-row justify-content-between align-items-center" do |ba|
|
134
|
+
ba.use :input, class: "form-select mx-1", error_class: "is-invalid", valid_class: "is-valid"
|
135
|
+
end
|
136
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback d-block"}
|
137
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
138
|
+
end
|
139
|
+
|
140
|
+
# vertical range input
|
141
|
+
config.wrappers :vertical_range, class: "mb-3" do |b|
|
142
|
+
b.use :html5
|
143
|
+
b.use :placeholder
|
144
|
+
b.optional :readonly
|
145
|
+
b.optional :step
|
146
|
+
b.use :label, class: "form-label"
|
147
|
+
b.use :input, class: "form-range", error_class: "is-invalid", valid_class: "is-valid"
|
148
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback"}
|
149
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
150
|
+
end
|
151
|
+
|
152
|
+
# horizontal forms
|
153
|
+
#
|
154
|
+
# horizontal default_wrapper
|
155
|
+
config.wrappers :horizontal_form, class: "row mb-3" do |b|
|
156
|
+
b.use :html5
|
157
|
+
b.use :placeholder
|
158
|
+
b.use :maxlength
|
159
|
+
b.use :minlength
|
160
|
+
b.optional :pattern
|
161
|
+
b.use :min_max
|
162
|
+
b.optional :readonly
|
163
|
+
b.use :label, class: "col-sm-3 col-form-label"
|
164
|
+
b.wrapper :grid_wrapper, class: "col-sm-9" do |ba|
|
165
|
+
ba.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid"
|
166
|
+
ba.use :full_error, wrap_with: {class: "invalid-feedback"}
|
167
|
+
ba.use :hint, wrap_with: {class: "form-text"}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# horizontal input for boolean
|
172
|
+
config.wrappers :horizontal_boolean, class: "row mb-3" do |b|
|
173
|
+
b.use :html5
|
174
|
+
b.optional :readonly
|
175
|
+
b.wrapper :grid_wrapper, class: "col-sm-9 offset-sm-3" do |wr|
|
176
|
+
wr.wrapper :form_check_wrapper, class: "form-check" do |bb|
|
177
|
+
bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
178
|
+
bb.use :label, class: "form-check-label"
|
179
|
+
bb.use :full_error, wrap_with: {class: "invalid-feedback"}
|
180
|
+
bb.use :hint, wrap_with: {class: "form-text"}
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# horizontal input for radio buttons and check boxes
|
186
|
+
config.wrappers :horizontal_collection, item_wrapper_class: "form-check", item_label_class: "form-check-label",
|
187
|
+
class: "row mb-3" do |b|
|
188
|
+
b.use :html5
|
189
|
+
b.optional :readonly
|
190
|
+
b.use :label, class: "col-sm-3 col-form-label pt-0"
|
191
|
+
b.wrapper :grid_wrapper, class: "col-sm-9" do |ba|
|
192
|
+
ba.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
193
|
+
ba.use :full_error, wrap_with: {class: "invalid-feedback d-block"}
|
194
|
+
ba.use :hint, wrap_with: {class: "form-text"}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# horizontal input for inline radio buttons and check boxes
|
199
|
+
config.wrappers :horizontal_collection_inline, item_wrapper_class: "form-check form-check-inline",
|
200
|
+
item_label_class: "form-check-label", class: "row mb-3" do |b|
|
201
|
+
b.use :html5
|
202
|
+
b.optional :readonly
|
203
|
+
b.use :label, class: "col-sm-3 col-form-label pt-0"
|
204
|
+
b.wrapper :grid_wrapper, class: "col-sm-9" do |ba|
|
205
|
+
ba.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
206
|
+
ba.use :full_error, wrap_with: {class: "invalid-feedback d-block"}
|
207
|
+
ba.use :hint, wrap_with: {class: "form-text"}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# horizontal file input
|
212
|
+
config.wrappers :horizontal_file, class: "row mb-3" do |b|
|
213
|
+
b.use :html5
|
214
|
+
b.use :placeholder
|
215
|
+
b.optional :maxlength
|
216
|
+
b.optional :minlength
|
217
|
+
b.optional :readonly
|
218
|
+
b.use :label, class: "col-sm-3 col-form-label"
|
219
|
+
b.wrapper tag: "div", html: {style: "display: flex; flex-direction: column-reverse;"} do |ba|
|
220
|
+
ba.optional :attachment
|
221
|
+
ba.wrapper :grid_wrapper, class: "col-sm-9" do |bc|
|
222
|
+
bc.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid"
|
223
|
+
bc.use :full_error, wrap_with: {class: "invalid-feedback"}
|
224
|
+
bc.use :hint, wrap_with: {class: "form-text"}
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# horizontal select input
|
230
|
+
config.wrappers :horizontal_select, class: "row mb-3" do |b|
|
231
|
+
b.use :html5
|
232
|
+
b.optional :readonly
|
233
|
+
b.use :label, class: "col-sm-3 col-form-label"
|
234
|
+
b.wrapper :grid_wrapper, class: "col-sm-9" do |ba|
|
235
|
+
ba.use :input, class: "form-select", error_class: "is-invalid", valid_class: "is-valid"
|
236
|
+
ba.use :full_error, wrap_with: {class: "invalid-feedback"}
|
237
|
+
ba.use :hint, wrap_with: {class: "form-text"}
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# horizontal multi select
|
242
|
+
config.wrappers :horizontal_multi_select, class: "row mb-3" do |b|
|
243
|
+
b.use :html5
|
244
|
+
b.optional :readonly
|
245
|
+
b.use :label, class: "col-sm-3 col-form-label"
|
246
|
+
b.wrapper :grid_wrapper, class: "col-sm-9" do |ba|
|
247
|
+
ba.wrapper class: "d-flex flex-row justify-content-between align-items-center" do |bb|
|
248
|
+
bb.use :input, class: "form-select mx-1", error_class: "is-invalid", valid_class: "is-valid"
|
249
|
+
end
|
250
|
+
ba.use :full_error, wrap_with: {class: "invalid-feedback d-block"}
|
251
|
+
ba.use :hint, wrap_with: {class: "form-text"}
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# horizontal range input
|
256
|
+
config.wrappers :horizontal_range, class: "row mb-3" do |b|
|
257
|
+
b.use :html5
|
258
|
+
b.use :placeholder
|
259
|
+
b.optional :readonly
|
260
|
+
b.optional :step
|
261
|
+
b.use :label, class: "col-sm-3 col-form-label pt-0"
|
262
|
+
b.wrapper :grid_wrapper, class: "col-sm-9" do |ba|
|
263
|
+
ba.use :input, class: "form-range", error_class: "is-invalid", valid_class: "is-valid"
|
264
|
+
ba.use :full_error, wrap_with: {class: "invalid-feedback"}
|
265
|
+
ba.use :hint, wrap_with: {class: "form-text"}
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# inline forms
|
270
|
+
#
|
271
|
+
# inline default_wrapper
|
272
|
+
config.wrappers :inline_form, class: "col-12" do |b|
|
273
|
+
b.use :html5
|
274
|
+
b.use :placeholder
|
275
|
+
b.use :maxlength
|
276
|
+
b.use :minlength
|
277
|
+
b.optional :pattern
|
278
|
+
b.use :min_max
|
279
|
+
b.optional :readonly
|
280
|
+
b.use :label, class: "visually-hidden"
|
281
|
+
|
282
|
+
b.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid"
|
283
|
+
b.use :error, wrap_with: {class: "invalid-feedback"}
|
284
|
+
b.optional :hint, wrap_with: {class: "form-text"}
|
285
|
+
end
|
286
|
+
|
287
|
+
# inline input for boolean
|
288
|
+
config.wrappers :inline_boolean, class: "col-12" do |b|
|
289
|
+
b.use :html5
|
290
|
+
b.optional :readonly
|
291
|
+
b.wrapper :form_check_wrapper, class: "form-check" do |bb|
|
292
|
+
bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
293
|
+
bb.use :label, class: "form-check-label"
|
294
|
+
bb.use :error, wrap_with: {class: "invalid-feedback"}
|
295
|
+
bb.optional :hint, wrap_with: {class: "form-text"}
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# bootstrap custom forms
|
300
|
+
#
|
301
|
+
# custom input switch for boolean
|
302
|
+
config.wrappers :custom_boolean_switch, class: "mb-3" do |b|
|
303
|
+
b.use :html5
|
304
|
+
b.optional :readonly
|
305
|
+
b.wrapper :form_check_wrapper, tag: "div", class: "form-check form-switch" do |bb|
|
306
|
+
bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid"
|
307
|
+
bb.use :label, class: "form-check-label"
|
308
|
+
bb.use :full_error, wrap_with: {tag: "div", class: "invalid-feedback"}
|
309
|
+
bb.use :hint, wrap_with: {class: "form-text"}
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# Input Group - custom component
|
314
|
+
# see example app and config at https://github.com/heartcombo/simple_form-bootstrap
|
315
|
+
config.wrappers :input_group, class: "mb-3" do |b|
|
316
|
+
b.use :html5
|
317
|
+
b.use :placeholder
|
318
|
+
b.use :maxlength
|
319
|
+
b.use :minlength
|
320
|
+
b.optional :pattern
|
321
|
+
b.use :min_max
|
322
|
+
b.optional :readonly
|
323
|
+
b.use :label, class: "form-label"
|
324
|
+
b.wrapper :input_group_tag, class: "input-group" do |ba|
|
325
|
+
ba.optional :prepend
|
326
|
+
ba.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid"
|
327
|
+
ba.optional :append
|
328
|
+
ba.use :full_error, wrap_with: {class: "invalid-feedback"}
|
329
|
+
end
|
330
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
331
|
+
end
|
332
|
+
|
333
|
+
# Floating Labels form
|
334
|
+
#
|
335
|
+
# floating labels default_wrapper
|
336
|
+
config.wrappers :floating_labels_form, class: "form-floating mb-3" do |b|
|
337
|
+
b.use :html5
|
338
|
+
b.use :placeholder
|
339
|
+
b.use :maxlength
|
340
|
+
b.use :minlength
|
341
|
+
b.optional :pattern
|
342
|
+
b.use :min_max
|
343
|
+
b.optional :readonly
|
344
|
+
b.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid"
|
345
|
+
b.use :label
|
346
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback"}
|
347
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
348
|
+
end
|
349
|
+
|
350
|
+
# custom multi select
|
351
|
+
config.wrappers :floating_labels_select, class: "form-floating mb-3" do |b|
|
352
|
+
b.use :html5
|
353
|
+
b.optional :readonly
|
354
|
+
b.use :input, class: "form-select", error_class: "is-invalid", valid_class: "is-valid"
|
355
|
+
b.use :label
|
356
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback"}
|
357
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
358
|
+
end
|
359
|
+
|
360
|
+
# slim-select
|
361
|
+
config.wrappers :slim_select, class: "mb-3" do |b|
|
362
|
+
b.optional :placeholder
|
363
|
+
b.optional :readonly
|
364
|
+
b.use :label, class: "form-label"
|
365
|
+
b.use :input, error_class: "is-invalid", valid_class: "is-valid", data: {controller: "slim-select"}
|
366
|
+
b.use :full_error, wrap_with: {class: "invalid-feedback"}
|
367
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
368
|
+
end
|
369
|
+
|
370
|
+
# quill
|
371
|
+
config.wrappers :quill, class: "mb-3" do |b|
|
372
|
+
b.use :label, class: "form-label"
|
373
|
+
b.wrapper tag: :div, html: {data: {controller: "quill-editor"}} do |quill|
|
374
|
+
quill.wrapper(tag: :div,
|
375
|
+
html: {
|
376
|
+
data: {quill_editor_target: "editor"}
|
377
|
+
}) {}
|
378
|
+
quill.use :input, error_class: "is-invalid", valid_class: "is-valid", class: "d-none",
|
379
|
+
data: {quill_editor_target: "input"}
|
380
|
+
quill.use :full_error, wrap_with: {class: "invalid-feedback"}
|
381
|
+
end
|
382
|
+
b.use :hint, wrap_with: {class: "form-text"}
|
383
|
+
end
|
384
|
+
|
385
|
+
# TODO: this will conflict with existing apps that use simple_form.
|
386
|
+
# A workaround would be to ensure their initializer loads after ours.
|
387
|
+
# Since this is for will deal with it when we get there
|
388
|
+
|
389
|
+
# The default wrapper to be used by the FormBuilder.
|
390
|
+
config.default_wrapper = :vertical_form
|
391
|
+
|
392
|
+
# Custom wrappers for input types. This should be a hash containing an input
|
393
|
+
# type as key and the wrapper that will be used for all inputs with specified type.
|
394
|
+
config.wrapper_mappings = {
|
395
|
+
boolean: :vertical_boolean,
|
396
|
+
check_boxes: :vertical_collection,
|
397
|
+
date: :vertical_multi_select,
|
398
|
+
datetime: :vertical_multi_select,
|
399
|
+
file: :vertical_file,
|
400
|
+
radio_buttons: :vertical_collection,
|
401
|
+
range: :vertical_range,
|
402
|
+
time: :vertical_multi_select,
|
403
|
+
select: :vertical_select
|
404
|
+
}
|
405
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Plutonium
|
4
|
+
module Lib
|
5
|
+
class AfterCommit
|
6
|
+
def initialize(rolled_back: false, &block)
|
7
|
+
@rolled_back = rolled_back
|
8
|
+
@callback = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def committed!(*)
|
12
|
+
@callback.call
|
13
|
+
end
|
14
|
+
|
15
|
+
def before_committed!(*)
|
16
|
+
end
|
17
|
+
|
18
|
+
def rolledback!(*)
|
19
|
+
@callback.call if @rolled_back
|
20
|
+
end
|
21
|
+
|
22
|
+
def trigger_transactional_callbacks?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def execute(rolled_back: false, connection: ActiveRecord::Base.connection, &block)
|
28
|
+
connection.transaction_open? ? connection.add_transaction_record(AfterCommit.new(rolled_back: rolled_back, &block)) : yield
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Lib
|
3
|
+
class BitFlags
|
4
|
+
delegate :sum, to: :indices
|
5
|
+
|
6
|
+
def initialize(*flags)
|
7
|
+
@map = flags.each_with_index.map { |flag, index| [flag, 2.pow(index)] }.to_h
|
8
|
+
end
|
9
|
+
|
10
|
+
def set?(value, *flags)
|
11
|
+
check = bits(*flags)
|
12
|
+
value & check == check
|
13
|
+
end
|
14
|
+
|
15
|
+
def extract(value)
|
16
|
+
@map.select { |_flag, bit| value & bit == bit }.keys
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](*flags)
|
20
|
+
bits(*flags)
|
21
|
+
end
|
22
|
+
|
23
|
+
def bits(*flags)
|
24
|
+
@map.slice(*flags).values.sum
|
25
|
+
end
|
26
|
+
|
27
|
+
def flags
|
28
|
+
@flags ||= @map.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def indices
|
32
|
+
@indices ||= @map.values
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Packaging
|
3
|
+
module App
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include Package
|
6
|
+
|
7
|
+
included do
|
8
|
+
isolate_namespace to_s.deconstantize.constantize
|
9
|
+
end
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
attr_reader :scoped_entity_class, :scoped_entity_param_key, :scoped_entity_strategy
|
13
|
+
|
14
|
+
def scope_to_entity(entity_class, param_key: nil, strategy: :path)
|
15
|
+
@scoped_entity_class = entity_class
|
16
|
+
@scoped_entity_strategy = strategy
|
17
|
+
@scoped_entity_param_key = param_key || entity_class.model_name.singular_route_key.to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def scoped_to_entity?
|
21
|
+
scoped_entity_class.present?
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize_register!
|
25
|
+
# this exists solely to support hot reloads
|
26
|
+
# if the user has modified the register especially if they removed a registration, we have no way of telling
|
27
|
+
# so instead we start over
|
28
|
+
@resource_register = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def register_resource(resource)
|
32
|
+
@resource_register.append resource
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource_register
|
36
|
+
@resource_register || []
|
37
|
+
end
|
38
|
+
|
39
|
+
def registered_resource_route_key_lookup
|
40
|
+
@registered_resource_route_key_lookup = resource_register.map { |resource|
|
41
|
+
[resource.model_name.singular_route_key.to_sym, resource]
|
42
|
+
}.to_h
|
43
|
+
end
|
44
|
+
|
45
|
+
def draw_resource_routes
|
46
|
+
registered_resources = resource_register
|
47
|
+
scoped_entity_param_key = self.scoped_entity_param_key
|
48
|
+
routes.draw do
|
49
|
+
shared_resource_concerns = [:interactive_resource_actions] # TODO: make this a config parameter
|
50
|
+
concern :interactive_resource_actions do
|
51
|
+
# these concerns power the interactive actions feature
|
52
|
+
member do
|
53
|
+
get "record_actions/:interactive_action", action: :begin_interactive_resource_record_action,
|
54
|
+
as: :interactive_resource_record_action
|
55
|
+
post "record_actions/:interactive_action", action: :commit_interactive_resource_record_action
|
56
|
+
end
|
57
|
+
|
58
|
+
collection do
|
59
|
+
get "collection_actions/:interactive_action", action: :begin_interactive_resource_collection_action,
|
60
|
+
as: :interactive_resource_collection_action
|
61
|
+
post "collection_actions/:interactive_action", action: :commit_interactive_resource_collection_action
|
62
|
+
|
63
|
+
get "recordless_actions/:interactive_action", action: :begin_interactive_resource_recordless_action,
|
64
|
+
as: :interactive_resource_recordless_action
|
65
|
+
post "recordless_actions/:interactive_action", action: :commit_interactive_resource_recordless_action
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
resource_route_names = []
|
70
|
+
resource_route_opts_lookup = {}
|
71
|
+
# for each of our registered resources, we are registering the routes required
|
72
|
+
registered_resources.each do |resource|
|
73
|
+
resource_name = resource.to_s # Deeply::Namespaced::ResourceModel
|
74
|
+
resource_controller = resource_name.pluralize.underscore # deeply/namespaced/resource_models
|
75
|
+
resource_route = resource.model_name.plural # deeply_namespaced_resource_models
|
76
|
+
resource_route_name = :"#{resource_route}_routes" # deeply_namespaced_resource_models_routes
|
77
|
+
|
78
|
+
resource_route_opts = {}
|
79
|
+
# rails is not smart enough to infer Deeply::Namespaced::ResourceModelsController from deeply_namespaced_resource_models
|
80
|
+
# since we are heavy on namespaces, we choose to be explicit to guarantee there is no confusion
|
81
|
+
resource_route_opts[:controller] = resource_controller
|
82
|
+
# using collection for path is much nicer than the alternative
|
83
|
+
# e.g. deeply/namespaced/resource_models vs deeply_namespaced_resource_models
|
84
|
+
resource_route_opts[:path] = resource.model_name.collection
|
85
|
+
resource_route_opts_lookup[resource_route] = resource_route_opts
|
86
|
+
|
87
|
+
# defining our resources with concerns allows us to defer materializing till later,
|
88
|
+
# ensuring that resource_route_opts_lookup is populated
|
89
|
+
concern resource_route_name do
|
90
|
+
resources resource_route, **resource_route_opts, concerns: shared_resource_concerns do
|
91
|
+
nested_resources_route_opts = resource_route_opts_lookup.slice(*resource.has_many_association_routes)
|
92
|
+
nested_resources_route_opts.each do |nested_resource_route, nested_resource_route_opts|
|
93
|
+
resources nested_resource_route, **nested_resource_route_opts, concerns: shared_resource_concerns
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
resource_route_names << resource_route_name
|
98
|
+
end
|
99
|
+
|
100
|
+
# materialize our routes using a scope
|
101
|
+
# if the app is scoped to an entity, ensure that the expected route param and url helper prefix are specified.
|
102
|
+
|
103
|
+
# path => /:entity/deeply/namespaced/resource_models/:deeply_namespaced_resource_model_id/
|
104
|
+
# helper => entity_deeply_namespaced_resource_models_path
|
105
|
+
scope_name = scoped_entity_param_key.present? ? ":#{scoped_entity_param_key}" : ""
|
106
|
+
|
107
|
+
# path => /deeply/namespaced/resource_models/:deeply_namespaced_resource_model_id/
|
108
|
+
# helper => deeply_namespaced_resource_models_path
|
109
|
+
scope_options = scoped_entity_param_key.present? ? {as: scoped_entity_param_key} : {}
|
110
|
+
|
111
|
+
scope scope_name, scope_options do
|
112
|
+
# we have to reverse sort our resource routes in order to prevent routing conflicts
|
113
|
+
# e.g. /blogs/1 and blogs/comments cause an issue if Blog is registered before Blogs::Comment
|
114
|
+
# attempting to load blogs/comments routes to blogs/:id which fails with a 404 since BlogsController
|
115
|
+
# essentially performs a Blog.find('comments')
|
116
|
+
# since the route names for these 2 will be 'blogs' and 'blog_comments',
|
117
|
+
# reverse sorting ensures that blog_comments is registered first, preventing the issue described above
|
118
|
+
concerns resource_route_names.sort.reverse
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Packaging
|
3
|
+
module Feature
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include Package
|
6
|
+
|
7
|
+
included do
|
8
|
+
initializer :append_migrations do |app|
|
9
|
+
unless app.root.to_s.match root.to_s
|
10
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
11
|
+
app.config.paths["db/migrate"] << expanded_path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Packaging
|
3
|
+
module Package
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# prevent this package from being added to the view lookup
|
8
|
+
# since we need finer control over how views are resolved.
|
9
|
+
# view lookup configuration is handled at the controller level
|
10
|
+
config.before_configuration do
|
11
|
+
# this touches the internals of rails, but I could not find a good way of doing this
|
12
|
+
# we get the initializer instance and set the block property to a noop
|
13
|
+
# There is no error handling, to ensure we know when it breaks.
|
14
|
+
add_view_paths_initializer = Rails.application.initializers.find do |a|
|
15
|
+
a.context_class == self && a.name.to_s == "add_view_paths"
|
16
|
+
end
|
17
|
+
add_view_paths_initializer.instance_variable_set(:@block, ->(app) {})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "pundit"
|
2
|
+
|
3
|
+
module Plutonium
|
4
|
+
module Policy
|
5
|
+
module Initializer
|
6
|
+
def initialize(context, record)
|
7
|
+
authorize!(context)
|
8
|
+
|
9
|
+
@context = context
|
10
|
+
@record = record
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_reader :context, :record
|
16
|
+
|
17
|
+
def authorize!(context)
|
18
|
+
raise Pundit::NotAuthorizedError, "must be logged in" unless context&.user
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|