plutonium 0.64.0 → 0.66.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 +4 -4
- data/.claude/skills/plutonium/SKILL.md +44 -41
- data/.claude/skills/plutonium-app/SKILL.md +115 -59
- data/.claude/skills/plutonium-async-interactions/SKILL.md +19 -19
- data/.claude/skills/plutonium-auth/SKILL.md +119 -53
- data/.claude/skills/plutonium-behavior/SKILL.md +110 -78
- data/.claude/skills/plutonium-dashboard/SKILL.md +168 -0
- data/.claude/skills/plutonium-kanban/SKILL.md +81 -49
- data/.claude/skills/plutonium-resource/SKILL.md +236 -145
- data/.claude/skills/plutonium-tenancy/SKILL.md +104 -55
- data/.claude/skills/plutonium-testing/SKILL.md +130 -33
- data/.claude/skills/plutonium-ui/SKILL.md +171 -95
- data/.claude/skills/plutonium-wizard/SKILL.md +93 -82
- data/CHANGELOG.md +80 -0
- data/CLAUDE.md +282 -210
- data/README.md +9 -9
- data/SECURITY.md +1 -1
- data/app/assets/plutonium-charts.js +20604 -0
- data/app/assets/plutonium-charts.js.map +7 -0
- data/app/assets/plutonium-charts.min.js +41 -0
- data/app/assets/plutonium-charts.min.js.map +7 -0
- data/app/assets/plutonium.css +1 -1
- data/app/assets/plutonium.js +794 -629
- data/app/assets/plutonium.js.map +4 -4
- data/app/assets/plutonium.min.js +48 -48
- data/app/assets/plutonium.min.js.map +4 -4
- data/app/views/plutonium/_flash_alerts.html.erb +2 -2
- data/app/views/plutonium/_resource_header.html.erb +2 -2
- data/app/views/plutonium/_resource_sidebar.html.erb +11 -2
- data/app/views/plutonium/_toast.html.erb +2 -2
- data/app/views/rodauth/_login_form.html.erb +1 -1
- data/app/views/rodauth/_password_visibility.html.erb +1 -1
- data/app/views/rodauth/add_recovery_codes.html.erb +2 -2
- data/app/views/rodauth/change_login.html.erb +2 -2
- data/app/views/rodauth/create_account.html.erb +4 -4
- data/app/views/rodauth/reset_password_request.html.erb +1 -1
- data/app/views/rodauth/verify_account_resend.html.erb +1 -1
- data/app/views/rodauth/webauthn_remove.html.erb +1 -1
- data/config/brakeman.ignore +4 -4
- data/config/initializers/rabl.rb +0 -40
- data/config/locales/en/api_client.yml +22 -0
- data/config/locales/en/async.yml +34 -0
- data/config/locales/en/dashboard.yml +25 -0
- data/config/locales/en/invites.yml +37 -0
- data/config/locales/en/js.yml +40 -0
- data/config/locales/en/kanban.yml +28 -0
- data/config/locales/en/plutonium.yml +26 -0
- data/config/locales/en/positioning.yml +14 -0
- data/config/locales/en/profile.yml +29 -0
- data/config/locales/en/resource.yml +60 -0
- data/config/locales/en/ui.yml +93 -0
- data/config/locales/en/wizard.yml +46 -0
- data/docs/.vitepress/config.ts +34 -1
- data/docs/.vitepress/sync-skills.mjs +6 -3
- data/docs/.vitepress/theme/components/HomeHero.vue +1 -1
- data/docs/.vitepress/theme/components/HomeInTheBox.vue +14 -0
- data/docs/.vitepress/theme/custom.css +34 -377
- data/docs/blog/introducing-plutonium-dashboards.md +174 -0
- data/docs/blog/introducing-plutonium-i18n.md +90 -0
- data/docs/blog/introducing-plutonium.md +4 -5
- data/docs/blog/whats-new-async-kanban-wizards.md +1 -1
- data/docs/getting-started/installation.md +5 -5
- data/docs/getting-started/tutorial/02-first-resource.md +3 -3
- data/docs/getting-started/tutorial/03-authentication.md +7 -7
- data/docs/getting-started/tutorial/04-authorization.md +21 -4
- data/docs/getting-started/tutorial/05-custom-actions.md +2 -2
- data/docs/getting-started/tutorial/06-nested-resources.md +5 -2
- data/docs/getting-started/tutorial/07-author-portal.md +2 -2
- data/docs/getting-started/tutorial/08-customizing-ui.md +45 -30
- data/docs/getting-started/tutorial/index.md +1 -1
- data/docs/guides/adding-resources.md +10 -7
- data/docs/guides/authentication.md +25 -25
- data/docs/guides/authorization.md +24 -24
- data/docs/guides/creating-packages.md +17 -17
- data/docs/guides/custom-actions.md +32 -32
- data/docs/guides/customizing-ui.md +29 -26
- data/docs/guides/dashboards.md +300 -0
- data/docs/guides/index.md +4 -3
- data/docs/guides/kanban.md +56 -56
- data/docs/guides/multi-tenancy.md +35 -22
- data/docs/guides/nested-resources.md +21 -21
- data/docs/guides/performance.md +3 -3
- data/docs/guides/search-filtering.md +13 -13
- data/docs/guides/testing.md +16 -12
- data/docs/guides/theming.md +32 -17
- data/docs/guides/troubleshooting.md +2 -2
- data/docs/guides/user-invites.md +17 -17
- data/docs/guides/user-profile.md +51 -24
- data/docs/guides/wizards.md +55 -55
- data/docs/public/images/blog/dashboards-card-error.png +0 -0
- data/docs/public/images/blog/dashboards-loading.png +0 -0
- data/docs/public/images/blog/dashboards-overview.png +0 -0
- data/docs/public/images/blog/dashboards-sidebar.png +0 -0
- data/docs/public/images/blog/i18n-es-admin.png +0 -0
- data/docs/public/images/guides/dashboard-card-error.png +0 -0
- data/docs/public/images/guides/dashboard-loading.png +0 -0
- data/docs/public/images/guides/dashboard-overview.png +0 -0
- data/docs/public/images/guides/dashboard-sidebar.png +0 -0
- data/docs/reference/app/generators.md +24 -24
- data/docs/reference/app/index.md +15 -18
- data/docs/reference/app/packages.md +8 -8
- data/docs/reference/app/portals.md +77 -29
- data/docs/reference/auth/accounts.md +15 -15
- data/docs/reference/auth/index.md +12 -12
- data/docs/reference/auth/profile.md +67 -29
- data/docs/reference/behavior/async-interactions.md +24 -24
- data/docs/reference/behavior/controllers.md +28 -28
- data/docs/reference/behavior/index.md +5 -5
- data/docs/reference/behavior/interactions.md +44 -44
- data/docs/reference/behavior/policies.md +48 -28
- data/docs/reference/configuration.md +88 -31
- data/docs/reference/dashboard/dsl.md +123 -0
- data/docs/reference/dashboard/index.md +35 -0
- data/docs/reference/dashboard/registration.md +76 -0
- data/docs/reference/generators/lite.md +7 -7
- data/docs/reference/i18n.md +262 -0
- data/docs/reference/index.md +11 -2
- data/docs/reference/kanban/authorization.md +9 -9
- data/docs/reference/kanban/dsl.md +33 -33
- data/docs/reference/kanban/index.md +1 -1
- data/docs/reference/kanban/positioning.md +18 -16
- data/docs/reference/resource/actions.md +51 -51
- data/docs/reference/resource/definition.md +166 -88
- data/docs/reference/resource/export.md +11 -7
- data/docs/reference/resource/index.md +16 -14
- data/docs/reference/resource/model.md +24 -24
- data/docs/reference/{positioning.md → resource/positioning.md} +78 -75
- data/docs/reference/resource/query.md +14 -12
- data/docs/reference/tenancy/entity-scoping.md +65 -35
- data/docs/reference/tenancy/index.md +11 -11
- data/docs/reference/tenancy/invites.md +20 -20
- data/docs/reference/tenancy/nested-resources.md +13 -13
- data/docs/reference/testing/index.md +116 -22
- data/docs/reference/ui/assets.md +65 -25
- data/docs/reference/ui/components.md +20 -20
- data/docs/reference/ui/displays.md +19 -22
- data/docs/reference/ui/forms.md +35 -35
- data/docs/reference/ui/index.md +17 -15
- data/docs/reference/ui/layouts.md +21 -21
- data/docs/reference/ui/pages.md +22 -22
- data/docs/reference/ui/tables.md +7 -7
- data/docs/reference/wizard/anchoring-resume.md +33 -32
- data/docs/reference/wizard/dsl.md +45 -45
- data/docs/reference/wizard/index.md +6 -6
- data/docs/reference/wizard/one-time.md +18 -18
- data/docs/reference/wizard/registration-launch.md +32 -32
- data/docs/reference/wizard/storage-config.md +23 -23
- data/esbuild.config.js +5 -2
- data/gemfiles/rails_7.gemfile.lock +2 -2
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/active_model/validations/array_validator.rb +1 -1
- data/lib/active_model/validations/attached_validator.rb +1 -1
- data/lib/active_model/validations/url_validator.rb +2 -2
- data/lib/generators/pu/core/assets/assets_generator.rb +36 -21
- data/lib/generators/pu/core/assets/templates/postcss.config.js +1 -1
- data/lib/generators/pu/core/update/update_generator.rb +3 -2
- data/lib/generators/pu/dashboard/dashboard_generator.rb +96 -0
- data/lib/generators/pu/dashboard/templates/dashboard.rb.tt +25 -0
- data/lib/generators/pu/docker/install/install_generator.rb +58 -0
- data/lib/generators/pu/docker/install/templates/Dockerfile.dev.tt +18 -3
- data/lib/generators/pu/docker/install/templates/Dockerfile.tt +20 -5
- data/lib/generators/pu/docker/install/templates/{docker-compose.yml → docker-compose.yml.tt} +1 -1
- data/lib/generators/pu/gem/dotenv/dotenv_generator.rb +1 -1
- data/lib/generators/pu/invites/invitable_generator.rb +18 -1
- data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +0 -95
- data/lib/generators/pu/lib/plutonium_generators/concerns/js_package_manager.rb +146 -0
- data/lib/generators/pu/lib/plutonium_generators/generator.rb +1 -17
- data/lib/generators/pu/pkg/package/package_generator.rb +1 -0
- data/lib/generators/pu/pkg/package/templates/config/locales/en.yml.tt +28 -0
- data/lib/generators/pu/pkg/portal/portal_generator.rb +1 -0
- data/lib/generators/pu/pkg/portal/templates/config/locales/en.yml.tt +30 -0
- data/lib/generators/pu/profile/conn_generator.rb +6 -0
- data/lib/generators/pu/res/scaffold/scaffold_generator.rb +0 -8
- data/lib/generators/pu/rodauth/concerns/feature_selector.rb +0 -18
- data/lib/plutonium/action/base.rb +27 -3
- data/lib/plutonium/action/interactive.rb +17 -4
- data/lib/plutonium/api_client/concerns/create_api_client.rb +12 -11
- data/lib/plutonium/api_client/concerns/disable_api_client.rb +3 -3
- data/lib/plutonium/auth/sequel_adapter.rb +1 -1
- data/lib/plutonium/configuration.rb +5 -0
- data/lib/plutonium/core/controller.rb +25 -1
- data/lib/plutonium/core/controllers/authorizable.rb +1 -1
- data/lib/plutonium/dashboard/base.rb +114 -0
- data/lib/plutonium/dashboard/card.rb +200 -0
- data/lib/plutonium/dashboard/controller.rb +101 -0
- data/lib/plutonium/dashboard/dsl.rb +104 -0
- data/lib/plutonium/dashboard/register.rb +40 -0
- data/lib/plutonium/dashboard/route_resolution.rb +30 -0
- data/lib/plutonium/dashboard.rb +42 -0
- data/lib/plutonium/definition/actions.rb +6 -1
- data/lib/plutonium/definition/base.rb +41 -3
- data/lib/plutonium/definition/index_views.rb +1 -1
- data/lib/plutonium/definition/positioning.rb +1 -1
- data/lib/plutonium/definition/presentable.rb +2 -2
- data/lib/plutonium/helpers/assets_helper.rb +15 -2
- data/lib/plutonium/helpers/display_helper.rb +10 -2
- data/lib/plutonium/interaction/async/context.rb +6 -8
- data/lib/plutonium/interaction/async/executor.rb +6 -7
- data/lib/plutonium/interaction/async/run.rb +2 -2
- data/lib/plutonium/interaction/async/run_definition.rb +1 -1
- data/lib/plutonium/interaction/base.rb +2 -0
- data/lib/plutonium/interaction/concerns/dispatchable.rb +15 -3
- data/lib/plutonium/invites/concerns/cancel_invite.rb +3 -3
- data/lib/plutonium/invites/concerns/invite_token.rb +25 -7
- data/lib/plutonium/invites/concerns/invite_user.rb +10 -5
- data/lib/plutonium/invites/concerns/resend_invite.rb +4 -4
- data/lib/plutonium/invites/controller.rb +11 -11
- data/lib/plutonium/kanban/column.rb +13 -3
- data/lib/plutonium/kanban/dsl.rb +7 -4
- data/lib/plutonium/models/has_cents.rb +1 -1
- data/lib/plutonium/profile/security_section.rb +10 -18
- data/lib/plutonium/query/filter.rb +10 -1
- data/lib/plutonium/query/filters/association.rb +27 -2
- data/lib/plutonium/query/filters/boolean.rb +4 -4
- data/lib/plutonium/query/filters/date.rb +4 -17
- data/lib/plutonium/query/filters/date_range.rb +2 -2
- data/lib/plutonium/query/filters/select.rb +10 -1
- data/lib/plutonium/query/filters/text.rb +9 -12
- data/lib/plutonium/railtie.rb +17 -0
- data/lib/plutonium/resource/controller.rb +10 -5
- data/lib/plutonium/resource/controllers/crud_actions.rb +17 -20
- data/lib/plutonium/resource/controllers/export_csv.rb +19 -9
- data/lib/plutonium/resource/controllers/kanban_actions.rb +16 -16
- data/lib/plutonium/resource/controllers/position_actions.rb +5 -5
- data/lib/plutonium/resource/controllers/typeahead.rb +24 -1
- data/lib/plutonium/resource/query_object.rb +30 -3
- data/lib/plutonium/resource/record/associated_with.rb +23 -2
- data/lib/plutonium/routing/dashboard_registration.rb +137 -0
- data/lib/plutonium/routing/resource_registration.rb +5 -0
- data/lib/plutonium/routing/route_set_extensions.rb +2 -1
- data/lib/plutonium/translation.rb +227 -0
- data/lib/plutonium/ui/actions_dropdown.rb +2 -2
- data/lib/plutonium/ui/breadcrumbs.rb +3 -3
- data/lib/plutonium/ui/color_mode_selector.rb +1 -1
- data/lib/plutonium/ui/component/behaviour.rb +46 -0
- data/lib/plutonium/ui/component/methods.rb +4 -0
- data/lib/plutonium/ui/dashboard/board.rb +80 -0
- data/lib/plutonium/ui/dashboard/card.rb +127 -0
- data/lib/plutonium/ui/dashboard/chart.rb +43 -0
- data/lib/plutonium/ui/dashboard/custom.rb +32 -0
- data/lib/plutonium/ui/dashboard/frame.rb +25 -0
- data/lib/plutonium/ui/dashboard/metric.rb +137 -0
- data/lib/plutonium/ui/dashboard/skeleton.rb +40 -0
- data/lib/plutonium/ui/display/components/attachment.rb +1 -1
- data/lib/plutonium/ui/display/components/badge.rb +7 -1
- data/lib/plutonium/ui/display/components/boolean.rb +2 -2
- data/lib/plutonium/ui/display/resource.rb +23 -16
- data/lib/plutonium/ui/export_button.rb +3 -3
- data/lib/plutonium/ui/form/components/key_value_store.rb +5 -5
- data/lib/plutonium/ui/form/components/password.rb +2 -2
- data/lib/plutonium/ui/form/components/resource_select.rb +27 -0
- data/lib/plutonium/ui/form/components/secure_association.rb +2 -0
- data/lib/plutonium/ui/form/components/uppy.rb +11 -3
- data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +1 -1
- data/lib/plutonium/ui/form/concerns/renders_repeater_row_controls.rb +5 -4
- data/lib/plutonium/ui/form/concerns/renders_structured_inputs.rb +1 -1
- data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +7 -1
- data/lib/plutonium/ui/form/query.rb +8 -8
- data/lib/plutonium/ui/form/resource.rb +54 -26
- data/lib/plutonium/ui/frame_navigator_panel.rb +4 -4
- data/lib/plutonium/ui/grid/card.rb +3 -3
- data/lib/plutonium/ui/grid/resource.rb +3 -3
- data/lib/plutonium/ui/interaction/async/run_progress.rb +6 -6
- data/lib/plutonium/ui/interaction/async/running_banner.rb +2 -2
- data/lib/plutonium/ui/kanban/column.rb +6 -6
- data/lib/plutonium/ui/layout/base.rb +19 -1
- data/lib/plutonium/ui/layout/header.rb +1 -1
- data/lib/plutonium/ui/layout/icon_rail.rb +4 -4
- data/lib/plutonium/ui/layout/rodauth_layout.rb +1 -1
- data/lib/plutonium/ui/layout/sidebar.rb +1 -1
- data/lib/plutonium/ui/layout/topbar.rb +2 -2
- data/lib/plutonium/ui/modal/base.rb +4 -4
- data/lib/plutonium/ui/nav_grid_menu.rb +1 -1
- data/lib/plutonium/ui/nav_user.rb +2 -2
- data/lib/plutonium/ui/page/base.rb +10 -2
- data/lib/plutonium/ui/page/dashboard.rb +54 -0
- data/lib/plutonium/ui/page/edit.rb +3 -3
- data/lib/plutonium/ui/page/interactive_action.rb +2 -2
- data/lib/plutonium/ui/page/new.rb +3 -3
- data/lib/plutonium/ui/page/show.rb +2 -2
- data/lib/plutonium/ui/page/wizard.rb +22 -16
- data/lib/plutonium/ui/page/wizard_chooser.rb +10 -10
- data/lib/plutonium/ui/page/wizard_completed.rb +2 -2
- data/lib/plutonium/ui/skeleton_table.rb +1 -1
- data/lib/plutonium/ui/table/base.rb +2 -2
- data/lib/plutonium/ui/table/components/attachment.rb +1 -1
- data/lib/plutonium/ui/table/components/bulk_actions_toolbar.rb +19 -3
- data/lib/plutonium/ui/table/components/drag_handle.rb +3 -3
- data/lib/plutonium/ui/table/components/filter_form.rb +11 -10
- data/lib/plutonium/ui/table/components/filter_pills.rb +4 -4
- data/lib/plutonium/ui/table/components/pagy_info.rb +61 -17
- data/lib/plutonium/ui/table/components/pagy_pagination.rb +9 -5
- data/lib/plutonium/ui/table/components/row_actions_dropdown.rb +1 -1
- data/lib/plutonium/ui/table/components/scopes_bar.rb +6 -2
- data/lib/plutonium/ui/table/components/scopes_pills.rb +3 -3
- data/lib/plutonium/ui/table/components/selection_column.rb +1 -1
- data/lib/plutonium/ui/table/components/toolbar.rb +2 -2
- data/lib/plutonium/ui/table/components/view_switcher.rb +12 -8
- data/lib/plutonium/ui/table/resource.rb +53 -17
- data/lib/plutonium/ui/wizard/review.rb +7 -7
- data/lib/plutonium/ui/wizard/stepper.rb +1 -1
- data/lib/plutonium/ui/wizard/summary_display.rb +6 -0
- data/lib/plutonium/version.rb +1 -1
- data/lib/plutonium/wizard/base.rb +2 -0
- data/lib/plutonium/wizard/driving.rb +8 -2
- data/lib/plutonium/wizard/dsl.rb +4 -2
- data/lib/plutonium/wizard/field_importer.rb +1 -8
- data/lib/plutonium/wizard/review_step.rb +8 -1
- data/lib/plutonium/wizard/step.rb +14 -3
- data/package.json +4 -2
- data/plutonium.gemspec +4 -1
- data/postcss-gem-import.cjs +34 -0
- data/postcss-gem-import.js +3 -28
- data/src/css/components.css +101 -10
- data/src/css/slim_select.css +0 -38
- data/src/css/tokens.css +24 -0
- data/src/js/controllers/attachment_input_controller.js +15 -6
- data/src/js/controllers/chart_controller.js +162 -0
- data/src/js/controllers/clipboard_controller.js +3 -2
- data/src/js/controllers/dirty_form_guard_controller.js +4 -3
- data/src/js/controllers/easymde_controller.js +3 -0
- data/src/js/controllers/filter_panel_controller.js +15 -6
- data/src/js/controllers/flatpickr_controller.js +8 -0
- data/src/js/controllers/frame_refresh_controller.js +59 -0
- data/src/js/controllers/intl_tel_input_controller.js +5 -0
- data/src/js/controllers/register_controllers.js +4 -0
- data/src/js/controllers/slim_select_controller.js +79 -176
- data/src/js/core.js +9 -1
- data/src/js/i18n.js +69 -0
- data/src/js/plutonium-charts.js +15 -0
- data/src/js/turbo/turbo_confirm.js +5 -3
- metadata +64 -16
- data/.yarnrc.yml +0 -8
- data/config/initializers/hotwire_turbo_monkey_patches.rb +0 -12
- data/lib/generators/pu/field/input/input_generator.rb +0 -32
- data/lib/generators/pu/field/input/templates/input.rb.tt +0 -15
- data/lib/generators/pu/lib/plutonium_generators/concerns/config.rb +0 -39
- data/lib/generators/pu/lib/plutonium_generators/concerns/serializer.rb +0 -39
- data/lib/generators/pu/lib/plutonium_generators/installer.rb +0 -205
- data/lib/generators/pu/res/scaffold/templates/presenter.rb.tt +0 -13
- data/lib/generators/pu/res/scaffold/templates/query_object.rb.tt +0 -17
- data/public/plutonium-assets/application.js +0 -31419
- data/public/plutonium-assets/plutonium.ico +0 -0
- data/yarn.lock +0 -6858
|
@@ -11,6 +11,11 @@ module Pu
|
|
|
11
11
|
|
|
12
12
|
desc "Set up docker for project"
|
|
13
13
|
|
|
14
|
+
# Fallbacks when the tool is not on PATH at generation time.
|
|
15
|
+
NODE_LTS_VERSION = "22.23.2"
|
|
16
|
+
YARN_CLASSIC_VERSION = "1.22.22"
|
|
17
|
+
BUN_VERSION = "1.4.2"
|
|
18
|
+
|
|
14
19
|
def start
|
|
15
20
|
in_root do
|
|
16
21
|
template "Dockerfile", force: true
|
|
@@ -30,6 +35,59 @@ module Pu
|
|
|
30
35
|
def ruby_version
|
|
31
36
|
@ruby_version ||= File.read(".ruby-version").strip
|
|
32
37
|
end
|
|
38
|
+
|
|
39
|
+
# The JavaScript toolchain is chosen the same way jsbundling-rails will
|
|
40
|
+
# choose it at `assets:precompile` inside the image, and versions come
|
|
41
|
+
# from the machine generating the Dockerfile (or NODE_VERSION /
|
|
42
|
+
# YARN_VERSION / BUN_VERSION), like Rails' own template.
|
|
43
|
+
def using_bun?
|
|
44
|
+
js_package_manager == :bun
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def dockerfile_node_version
|
|
48
|
+
ENV.fetch("NODE_VERSION") { node_version || NODE_LTS_VERSION }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def dockerfile_yarn_version
|
|
52
|
+
ENV.fetch("YARN_VERSION") { yarn_version || YARN_CLASSIC_VERSION }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def dockerfile_bun_version
|
|
56
|
+
ENV.fetch("BUN_VERSION") { bun_version || BUN_VERSION }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Yarn 2+ is installed through corepack, and its lockfile flag is
|
|
60
|
+
# --immutable rather than yarn 1's --frozen-lockfile.
|
|
61
|
+
def yarn_through_corepack?
|
|
62
|
+
js_package_manager == :yarn && dockerfile_yarn_version.to_i >= 2
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def js_lockfile_copy
|
|
66
|
+
case js_package_manager
|
|
67
|
+
when :bun then "package.json bun.lock*"
|
|
68
|
+
when :pnpm then "package.json pnpm-lock.yaml"
|
|
69
|
+
when :npm then "package.json package-lock.json"
|
|
70
|
+
# .yarnrc.yml carries nodeLinker for yarn 2+; the glob keeps the COPY
|
|
71
|
+
# valid on yarn 1 apps that have none.
|
|
72
|
+
else "package.json yarn.lock .yarnrc.yml*"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def js_frozen_install_command
|
|
77
|
+
case js_package_manager
|
|
78
|
+
when :bun then "bun install --frozen-lockfile"
|
|
79
|
+
when :pnpm then "pnpm install --frozen-lockfile"
|
|
80
|
+
when :npm then "npm ci"
|
|
81
|
+
else "yarn install --#{yarn_through_corepack? ? "immutable" : "frozen-lockfile"}"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# docker-compose runs this on every container start. `npm ci` would wipe
|
|
86
|
+
# node_modules each boot and fails without a package-lock.json, so npm
|
|
87
|
+
# gets a plain install; the others already only sync what changed.
|
|
88
|
+
def js_dev_install_command
|
|
89
|
+
(js_package_manager == :npm) ? "npm install" : js_install_command
|
|
90
|
+
end
|
|
33
91
|
end
|
|
34
92
|
end
|
|
35
93
|
end
|
|
@@ -11,13 +11,28 @@ RUN apt-get update -qq && \
|
|
|
11
11
|
apt-get install --no-install-recommends -y build-essential curl git libpq-dev node-gyp pkg-config python-is-python3
|
|
12
12
|
|
|
13
13
|
# Install JavaScript dependencies
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
<% if using_bun? -%>
|
|
15
|
+
ENV BUN_INSTALL=/usr/local/bun
|
|
16
|
+
ENV PATH=/usr/local/bun/bin:$PATH
|
|
17
|
+
ARG BUN_VERSION=<%= dockerfile_bun_version %>
|
|
18
|
+
RUN curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"
|
|
19
|
+
<% else -%>
|
|
20
|
+
ARG NODE_VERSION=<%= dockerfile_node_version %>
|
|
16
21
|
ENV PATH=/usr/local/node/bin:$PATH
|
|
17
22
|
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
|
|
18
23
|
/tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
|
|
19
|
-
npm install -g yarn@$YARN_VERSION && \
|
|
20
24
|
rm -rf /tmp/node-build-master
|
|
25
|
+
<% if js_package_manager == :yarn -%>
|
|
26
|
+
ARG YARN_VERSION=<%= dockerfile_yarn_version %>
|
|
27
|
+
<% if yarn_through_corepack? -%>
|
|
28
|
+
RUN corepack enable && corepack install -g yarn@$YARN_VERSION
|
|
29
|
+
<% else -%>
|
|
30
|
+
RUN npm install -g yarn@$YARN_VERSION
|
|
31
|
+
<% end -%>
|
|
32
|
+
<% elsif js_package_manager == :pnpm -%>
|
|
33
|
+
RUN corepack enable && corepack install -g pnpm@latest
|
|
34
|
+
<% end -%>
|
|
35
|
+
<% end -%>
|
|
21
36
|
|
|
22
37
|
# Additional dependencies go here
|
|
23
38
|
|
|
@@ -22,13 +22,28 @@ RUN apt-get update -qq && \
|
|
|
22
22
|
apt-get install --no-install-recommends -y build-essential curl git libpq-dev node-gyp pkg-config python-is-python3
|
|
23
23
|
|
|
24
24
|
# Install JavaScript dependencies
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
<% if using_bun? -%>
|
|
26
|
+
ENV BUN_INSTALL=/usr/local/bun
|
|
27
|
+
ENV PATH=/usr/local/bun/bin:$PATH
|
|
28
|
+
ARG BUN_VERSION=<%= dockerfile_bun_version %>
|
|
29
|
+
RUN curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"
|
|
30
|
+
<% else -%>
|
|
31
|
+
ARG NODE_VERSION=<%= dockerfile_node_version %>
|
|
27
32
|
ENV PATH=/usr/local/node/bin:$PATH
|
|
28
33
|
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
|
|
29
34
|
/tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
|
|
30
|
-
npm install -g yarn@$YARN_VERSION && \
|
|
31
35
|
rm -rf /tmp/node-build-master
|
|
36
|
+
<% if js_package_manager == :yarn -%>
|
|
37
|
+
ARG YARN_VERSION=<%= dockerfile_yarn_version %>
|
|
38
|
+
<% if yarn_through_corepack? -%>
|
|
39
|
+
RUN corepack enable && corepack install -g yarn@$YARN_VERSION
|
|
40
|
+
<% else -%>
|
|
41
|
+
RUN npm install -g yarn@$YARN_VERSION
|
|
42
|
+
<% end -%>
|
|
43
|
+
<% elsif js_package_manager == :pnpm -%>
|
|
44
|
+
RUN corepack enable && corepack install -g pnpm@latest
|
|
45
|
+
<% end -%>
|
|
46
|
+
<% end -%>
|
|
32
47
|
|
|
33
48
|
# Install application gems
|
|
34
49
|
COPY .ruby-version Gemfile Gemfile.lock ./
|
|
@@ -37,8 +52,8 @@ RUN bundle install && \
|
|
|
37
52
|
bundle exec bootsnap precompile --gemfile
|
|
38
53
|
|
|
39
54
|
# Install node modules
|
|
40
|
-
COPY
|
|
41
|
-
RUN
|
|
55
|
+
COPY <%= js_lockfile_copy %> ./
|
|
56
|
+
RUN <%= js_frozen_install_command %>
|
|
42
57
|
|
|
43
58
|
# Copy application code
|
|
44
59
|
COPY . .
|
data/lib/generators/pu/docker/install/templates/{docker-compose.yml → docker-compose.yml.tt}
RENAMED
|
@@ -22,7 +22,7 @@ x-app: &app
|
|
|
22
22
|
services:
|
|
23
23
|
web:
|
|
24
24
|
<<: *app
|
|
25
|
-
command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle &&
|
|
25
|
+
command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle && <%= js_dev_install_command %> && bin/dev" # web
|
|
26
26
|
# web properties
|
|
27
27
|
ports: # web
|
|
28
28
|
- "3000:3000" # app
|
|
@@ -19,7 +19,7 @@ module Pu
|
|
|
19
19
|
|
|
20
20
|
copy_file "config/initializers/001_ensure_required_env.rb"
|
|
21
21
|
|
|
22
|
-
gitignore "!/.env", "!/.env.template", "!/.env.local.template"
|
|
22
|
+
gitignore "!/.env", "!/.env.template", "!/.env.local.template"
|
|
23
23
|
|
|
24
24
|
insert_into_file "Gemfile", "\ngem \"dotenv\", groups: %i[development test]\n", after: /^gem ["']rails["'].*\n/
|
|
25
25
|
bundle!
|
|
@@ -22,7 +22,7 @@ module Pu
|
|
|
22
22
|
desc: "The user model name"
|
|
23
23
|
|
|
24
24
|
class_option :membership_model, type: :string,
|
|
25
|
-
desc: "The membership model name (
|
|
25
|
+
desc: "The membership model name (e.g. OrganizationUser). When omitted, the generated interaction has no membership_class override and you must implement it yourself"
|
|
26
26
|
|
|
27
27
|
class_option :dest, type: :string, default: "main_app",
|
|
28
28
|
desc: "Destination package for the interaction"
|
|
@@ -51,6 +51,23 @@ module Pu
|
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
def warn_membership_model_default
|
|
55
|
+
return if behavior == :revoke
|
|
56
|
+
return if options[:membership_model].present?
|
|
57
|
+
|
|
58
|
+
say_status :warning,
|
|
59
|
+
"No --membership-model specified — generated interaction will not include a membership_class override.",
|
|
60
|
+
:yellow
|
|
61
|
+
say <<~MSG.indent(2)
|
|
62
|
+
|
|
63
|
+
The generated #{model_class}::InviteUserInteraction raises
|
|
64
|
+
NotImplementedError from #membership_class at runtime until you either:
|
|
65
|
+
- re-run with --membership-model=NAME (e.g. --membership-model=OrganizationUser), or
|
|
66
|
+
- manually override #membership_class to return your membership join model.
|
|
67
|
+
|
|
68
|
+
MSG
|
|
69
|
+
end
|
|
70
|
+
|
|
54
71
|
def create_interaction
|
|
55
72
|
template "invitable/invite_user_interaction.rb",
|
|
56
73
|
interaction_path
|
|
@@ -29,101 +29,6 @@ module PlutoniumGenerators
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
# #
|
|
33
|
-
# # Adds a new gem into the Gemfile
|
|
34
|
-
# # Existing directives are updated if they do not match
|
|
35
|
-
# # When `:group` is specified, the gem is inserted into the approriate gem group.
|
|
36
|
-
# #
|
|
37
|
-
# # @param [String] name the name of the gem
|
|
38
|
-
# # @param [Hash] **kwargs set of options to append see #super
|
|
39
|
-
# #
|
|
40
|
-
# # @return [void]
|
|
41
|
-
# #
|
|
42
|
-
# def gem(name, **kwargs)
|
|
43
|
-
# groups = Array(kwargs.delete(:group))
|
|
44
|
-
|
|
45
|
-
# in_root do
|
|
46
|
-
# begin
|
|
47
|
-
# # Create a temp gemfile
|
|
48
|
-
# File.rename("Gemfile", "Gemfile.bak")
|
|
49
|
-
# File.write("Gemfile", "")
|
|
50
|
-
# # Generate the directive
|
|
51
|
-
# super
|
|
52
|
-
# # Get the generated directive
|
|
53
|
-
# directive = gemfile.strip
|
|
54
|
-
# ensure
|
|
55
|
-
# # Restore our gemfile
|
|
56
|
-
# File.delete "Gemfile"
|
|
57
|
-
# File.rename "Gemfile.bak", "Gemfile"
|
|
58
|
-
# end
|
|
59
|
-
|
|
60
|
-
# pattern = /^# gem ['"]#{name}['"].*/
|
|
61
|
-
# if gemfile.match(pattern)
|
|
62
|
-
# # Replace commented out directive
|
|
63
|
-
# gsub_file("Gemfile", pattern, directive)
|
|
64
|
-
# break
|
|
65
|
-
# end
|
|
66
|
-
|
|
67
|
-
# # Remove existing directive
|
|
68
|
-
# remove_gem name
|
|
69
|
-
|
|
70
|
-
# # Insert the new directive
|
|
71
|
-
# if groups != []
|
|
72
|
-
# str = groups.sort.map(&:inspect).join(", ")
|
|
73
|
-
# after_sentinel = "group #{str} do\n"
|
|
74
|
-
|
|
75
|
-
# unless File.read("Gemfile").match?(/^#{after_sentinel}/)
|
|
76
|
-
# inject_into_file "Gemfile", "\n#{after_sentinel}end\n"
|
|
77
|
-
# end
|
|
78
|
-
# else
|
|
79
|
-
# after_sentinel = "# Project gems\n\n"
|
|
80
|
-
# unless File.read("Gemfile").match?(/^#{after_sentinel}/)
|
|
81
|
-
# inject_into_file "Gemfile", "\n#{after_sentinel}", after: /^ruby .*\n/
|
|
82
|
-
# end
|
|
83
|
-
# end
|
|
84
|
-
|
|
85
|
-
# inject_into_file "Gemfile", "#{directive}\n", after: /^#{after_sentinel}/
|
|
86
|
-
# end
|
|
87
|
-
# end
|
|
88
|
-
|
|
89
|
-
# #
|
|
90
|
-
# # Removes a gem and any preceeding comments from the Gemfile
|
|
91
|
-
# #
|
|
92
|
-
# # @param gem [String] the name of the gem to remove
|
|
93
|
-
# #
|
|
94
|
-
# # @return [void]
|
|
95
|
-
# #
|
|
96
|
-
# def remove_gem(gem)
|
|
97
|
-
# log :remove_gem, gem
|
|
98
|
-
# gsub_file "Gemfile", /(:?^.*#.*\n)*.*gem ['"]#{gem}['"].*\n/, "", verbose: false
|
|
99
|
-
# end
|
|
100
|
-
|
|
101
|
-
# #
|
|
102
|
-
# # Evaluates the given template and merges it with the project's docker-compose.yml
|
|
103
|
-
# #
|
|
104
|
-
# # @param [String] source the template filename
|
|
105
|
-
# #
|
|
106
|
-
# # @return [void]
|
|
107
|
-
# #
|
|
108
|
-
# def docker_compose(source)
|
|
109
|
-
# log :docker_compose, source
|
|
110
|
-
|
|
111
|
-
# in_root do
|
|
112
|
-
# compose_file = "docker-compose.yml"
|
|
113
|
-
# compose_definition = YAML.load_file(compose_file) if File.exist?(compose_file)
|
|
114
|
-
# compose_definition ||= {
|
|
115
|
-
# version: "3.7",
|
|
116
|
-
# services: {}
|
|
117
|
-
# }
|
|
118
|
-
# compose_definition.deep_stringify_keys!
|
|
119
|
-
|
|
120
|
-
# new_definition = YAML.load template_eval("docker-compose/#{source}.yml.tt")
|
|
121
|
-
# compose_definition.deep_merge! new_definition.deep_stringify_keys
|
|
122
|
-
|
|
123
|
-
# create_file compose_file, YAML.dump(compose_definition), force: true
|
|
124
|
-
# end
|
|
125
|
-
# end
|
|
126
|
-
|
|
127
32
|
def managed_compose(file = "docker-compose.yml")
|
|
128
33
|
@managed_compose ||= {}
|
|
129
34
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
# jsbundling-rails `main` ships the detector its build task uses (unreleased
|
|
5
|
+
# as of 1.3.1).
|
|
6
|
+
require "jsbundling/package_manager"
|
|
7
|
+
rescue LoadError
|
|
8
|
+
# Older jsbundling-rails, or an app without it: fall back to the same rules.
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module PlutoniumGenerators
|
|
12
|
+
module Concerns
|
|
13
|
+
# Detects the host app's JavaScript package manager and builds the matching
|
|
14
|
+
# shell commands, so generators never hardcode `yarn`.
|
|
15
|
+
#
|
|
16
|
+
# Detection follows what `rails javascript:build` consults at precompile
|
|
17
|
+
# time. Installing with the same tool keeps a single lockfile: the lockfile
|
|
18
|
+
# decides, and with no lockfile the first executable on PATH among bun,
|
|
19
|
+
# yarn, pnpm and npm wins (yarn when none is found). `rails new -j esbuild`
|
|
20
|
+
# therefore yields a bun app on any machine that has bun installed, and
|
|
21
|
+
# this concern follows it rather than adding a yarn.lock next to bun.lock.
|
|
22
|
+
# When the app's jsbundling-rails provides Jsbundling::PackageManager, that
|
|
23
|
+
# detector is used as is (it skips yarn.lock and decides by PATH).
|
|
24
|
+
#
|
|
25
|
+
# Yarn 1 (classic) and Yarn 2+ (berry) share `add` but differ elsewhere;
|
|
26
|
+
# `yarn_berry?` distinguishes them by asking the yarn the app resolves to.
|
|
27
|
+
module JsPackageManager
|
|
28
|
+
ADD_COMMANDS = {
|
|
29
|
+
bun: "bun add %s",
|
|
30
|
+
pnpm: "pnpm add %s",
|
|
31
|
+
npm: "npm install %s",
|
|
32
|
+
yarn: "yarn add %s"
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
INSTALL_COMMANDS = {
|
|
36
|
+
bun: "bun install",
|
|
37
|
+
pnpm: "pnpm install",
|
|
38
|
+
npm: "npm ci",
|
|
39
|
+
yarn: "yarn install"
|
|
40
|
+
}.freeze
|
|
41
|
+
|
|
42
|
+
RUN_COMMANDS = {
|
|
43
|
+
bun: "bun run %s",
|
|
44
|
+
pnpm: "pnpm run %s",
|
|
45
|
+
npm: "npm run %s",
|
|
46
|
+
yarn: "yarn %s"
|
|
47
|
+
}.freeze
|
|
48
|
+
|
|
49
|
+
LOCKFILES = {
|
|
50
|
+
bun: %w[bun.lock bun.lockb],
|
|
51
|
+
pnpm: %w[pnpm-lock.yaml],
|
|
52
|
+
npm: %w[package-lock.json],
|
|
53
|
+
yarn: %w[yarn.lock]
|
|
54
|
+
}.freeze
|
|
55
|
+
|
|
56
|
+
protected
|
|
57
|
+
|
|
58
|
+
# @return [Symbol] one of :bun, :pnpm, :npm, :yarn
|
|
59
|
+
def js_package_manager
|
|
60
|
+
@js_package_manager ||= detect_js_package_manager
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# One command that adds every package. `pkg@latest` and `pkg@^1.2.3`
|
|
64
|
+
# are understood identically by all four managers, which is why callers
|
|
65
|
+
# pass versions inline instead of running a separate upgrade step
|
|
66
|
+
# (yarn 1 `upgrade --latest` has no yarn 2+ equivalent).
|
|
67
|
+
def js_add_command(*packages)
|
|
68
|
+
format(ADD_COMMANDS.fetch(js_package_manager), packages.flatten.join(" "))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def js_install_command
|
|
72
|
+
INSTALL_COMMANDS.fetch(js_package_manager)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def js_run_command(script)
|
|
76
|
+
format(RUN_COMMANDS.fetch(js_package_manager), script)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Yarn 2+ ("berry"). Asks the yarn the app resolves to, so corepack and
|
|
80
|
+
# a `packageManager` field are honoured.
|
|
81
|
+
def yarn_berry?
|
|
82
|
+
js_package_manager == :yarn && yarn_version.to_i >= 2
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def yarn_version
|
|
86
|
+
@yarn_version ||= capture_tool_version("yarn --version")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def bun_version
|
|
90
|
+
@bun_version ||= capture_tool_version("bun --version")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def node_version
|
|
94
|
+
@node_version ||= capture_tool_version("node --version")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Yarn 2+ defaults to Plug'n'Play, which Tailwind's PostCSS plugin cannot
|
|
98
|
+
# be loaded under (postcss-load-config's require() options are not
|
|
99
|
+
# supported by PnP). Pin the node-modules linker, which is what the rest
|
|
100
|
+
# of the Rails toolchain expects, unless the app already chose a linker.
|
|
101
|
+
def ensure_yarn_node_modules_linker
|
|
102
|
+
return unless yarn_berry?
|
|
103
|
+
|
|
104
|
+
yarnrc = ".yarnrc.yml"
|
|
105
|
+
existing = in_root_dir { File.exist?(yarnrc) ? File.read(yarnrc) : nil }
|
|
106
|
+
|
|
107
|
+
if existing.nil?
|
|
108
|
+
create_file yarnrc, "nodeLinker: node-modules\n"
|
|
109
|
+
elsif existing.match?(/^nodeLinker:/)
|
|
110
|
+
unless existing.match?(/^nodeLinker:\s*node-modules\b/)
|
|
111
|
+
warn "#{yarnrc} sets a nodeLinker other than node-modules; the Tailwind PostCSS plugin does not load under Plug'n'Play"
|
|
112
|
+
end
|
|
113
|
+
else
|
|
114
|
+
append_to_file yarnrc, "nodeLinker: node-modules\n"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
def detect_js_package_manager
|
|
121
|
+
root = Pathname(destination_root)
|
|
122
|
+
return Jsbundling::PackageManager.detect(root) if defined?(Jsbundling::PackageManager)
|
|
123
|
+
|
|
124
|
+
LOCKFILES.each do |manager, files|
|
|
125
|
+
return manager if files.any? { |f| root.join(f).exist? }
|
|
126
|
+
end
|
|
127
|
+
return :bun if root.join("bun.config.js").exist?
|
|
128
|
+
|
|
129
|
+
%i[bun yarn pnpm npm].find { |exe| system("command -v #{exe} > /dev/null") } || :yarn
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def capture_tool_version(command)
|
|
133
|
+
output = in_root_dir { `#{command} 2>/dev/null` }
|
|
134
|
+
output[/\d+\.\d+\.\d+/]
|
|
135
|
+
rescue SystemCallError
|
|
136
|
+
nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Thor's in_root returns the block value too, but only once the generator
|
|
140
|
+
# has a destination stack; this stays usable from plain unit tests.
|
|
141
|
+
def in_root_dir(&)
|
|
142
|
+
Dir.chdir(destination_root, &)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -5,10 +5,9 @@ require "tty-prompt"
|
|
|
5
5
|
|
|
6
6
|
module PlutoniumGenerators
|
|
7
7
|
module Generator
|
|
8
|
-
include Concerns::Config
|
|
9
8
|
include Concerns::Logger
|
|
10
|
-
include Concerns::Serializer
|
|
11
9
|
include Concerns::Actions
|
|
10
|
+
include Concerns::JsPackageManager
|
|
12
11
|
|
|
13
12
|
# Finds the shared namespace prefix between two model names.
|
|
14
13
|
# Used to derive association names when models share a namespace.
|
|
@@ -58,20 +57,5 @@ module PlutoniumGenerators
|
|
|
58
57
|
TTY::Prompt.new
|
|
59
58
|
end
|
|
60
59
|
end
|
|
61
|
-
|
|
62
|
-
# def appname
|
|
63
|
-
# defined?(Rails.application) ? Rails.application.class.module_parent.name : "PlutoniumGenerators"
|
|
64
|
-
# end
|
|
65
|
-
|
|
66
|
-
# def app_name
|
|
67
|
-
# appname.underscore
|
|
68
|
-
# end
|
|
69
|
-
|
|
70
|
-
def pug_installed?(feature, version: nil)
|
|
71
|
-
installed_version = read_config(:installed, feature)
|
|
72
|
-
return false unless installed_version.present?
|
|
73
|
-
|
|
74
|
-
version.present? ? SemanticRange.satisfies?(installed_version, ">=#{version}") : true
|
|
75
|
-
end
|
|
76
60
|
end
|
|
77
61
|
end
|
|
@@ -17,6 +17,7 @@ module Pu
|
|
|
17
17
|
validate_package_name package_name
|
|
18
18
|
|
|
19
19
|
template "lib/engine.rb", "packages/#{package_namespace}/lib/engine.rb"
|
|
20
|
+
template "config/locales/en.yml", "packages/#{package_namespace}/config/locales/en.yml"
|
|
20
21
|
|
|
21
22
|
%w[controllers interactions models policies definitions].each do |dir|
|
|
22
23
|
directory "app/#{dir}", "packages/#{package_namespace}/app/#{dir}/#{package_namespace}"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Wording for the <%= package_name %> package's resources.
|
|
2
|
+
#
|
|
3
|
+
# This file is loaded automatically (the package is a Rails engine) ahead of
|
|
4
|
+
# the host app's config/locales, so the app can still override anything here.
|
|
5
|
+
#
|
|
6
|
+
# Model and attribute names follow the Rails convention; placeholders, hints
|
|
7
|
+
# and derived labels follow Plutonium's:
|
|
8
|
+
#
|
|
9
|
+
# en:
|
|
10
|
+
# activerecord:
|
|
11
|
+
# models:
|
|
12
|
+
# <%= package_namespace %>/post:
|
|
13
|
+
# one: "Post"
|
|
14
|
+
# other: "Posts"
|
|
15
|
+
# attributes:
|
|
16
|
+
# <%= package_namespace %>/post:
|
|
17
|
+
# title: "Title"
|
|
18
|
+
# plutonium:
|
|
19
|
+
# fields:
|
|
20
|
+
# <%= package_namespace %>/post:
|
|
21
|
+
# title:
|
|
22
|
+
# placeholder: "A short, descriptive title"
|
|
23
|
+
# actions:
|
|
24
|
+
# <%= package_namespace %>/post:
|
|
25
|
+
# publish: "Publish now"
|
|
26
|
+
#
|
|
27
|
+
# See https://radioactive-labs.github.io/plutonium-core/reference/i18n
|
|
28
|
+
en: {}
|
|
@@ -25,6 +25,7 @@ module Pu
|
|
|
25
25
|
|
|
26
26
|
template "lib/engine.rb", "packages/#{package_namespace}/lib/engine.rb"
|
|
27
27
|
template "config/routes.rb", "packages/#{package_namespace}/config/routes.rb"
|
|
28
|
+
template "config/locales/en.yml", "packages/#{package_namespace}/config/locales/en.yml"
|
|
28
29
|
|
|
29
30
|
template "app/controllers/concerns/controller.rb",
|
|
30
31
|
"packages/#{package_namespace}/app/controllers/#{package_namespace}/concerns/controller.rb"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Wording specific to the <%= package_name %> portal.
|
|
2
|
+
#
|
|
3
|
+
# This file is loaded automatically (the portal is a Rails engine) ahead of the
|
|
4
|
+
# host app's config/locales: anything here overrides Plutonium's defaults for
|
|
5
|
+
# this portal, and the app's own locale files override this.
|
|
6
|
+
#
|
|
7
|
+
# Portal-specific text for a resource goes under
|
|
8
|
+
# plutonium.portals.<%= package_namespace %>, mirroring the global keys:
|
|
9
|
+
#
|
|
10
|
+
# en:
|
|
11
|
+
# plutonium:
|
|
12
|
+
# portals:
|
|
13
|
+
# <%= package_namespace %>:
|
|
14
|
+
# fields:
|
|
15
|
+
# blogging/post:
|
|
16
|
+
# title:
|
|
17
|
+
# placeholder: "Working title"
|
|
18
|
+
# hint: "Shown in the sidebar"
|
|
19
|
+
# actions:
|
|
20
|
+
# blogging/post:
|
|
21
|
+
# publish: "Publish to site"
|
|
22
|
+
# scopes:
|
|
23
|
+
# blogging/post:
|
|
24
|
+
# drafts: "Drafts"
|
|
25
|
+
#
|
|
26
|
+
# See https://radioactive-labs.github.io/plutonium-core/reference/i18n
|
|
27
|
+
en:
|
|
28
|
+
plutonium:
|
|
29
|
+
portals:
|
|
30
|
+
<%= package_namespace %>: {}
|
|
@@ -65,6 +65,12 @@ module Pu
|
|
|
65
65
|
user.#{profile_association}.nil?
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
# The base update? delegates to create?, which is false once the profile
|
|
69
|
+
# exists. relation_scope already limits this to the user's own profile.
|
|
70
|
+
def update?
|
|
71
|
+
true
|
|
72
|
+
end
|
|
73
|
+
|
|
68
74
|
def destroy?
|
|
69
75
|
false
|
|
70
76
|
end
|
|
@@ -49,14 +49,6 @@ module Pu
|
|
|
49
49
|
template "definition.rb", File.join("app/definitions", class_path, "#{file_name}_definition.rb")
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
# def create_presenter
|
|
53
|
-
# template "presenter.rb", File.join("app/presenters", class_path, "#{file_name}_presenter.rb")
|
|
54
|
-
# end
|
|
55
|
-
|
|
56
|
-
# def create_query_object
|
|
57
|
-
# template "query_object.rb", File.join("app/query_objects", class_path, "#{file_name}_query_object.rb")
|
|
58
|
-
# end
|
|
59
|
-
|
|
60
52
|
private
|
|
61
53
|
|
|
62
54
|
def default_policy_attributes
|
|
@@ -64,24 +64,6 @@ module Pu
|
|
|
64
64
|
options[feature]
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
# Creates a hash of options to pass down options to an invoked sub generator
|
|
68
|
-
def invoke_options
|
|
69
|
-
# These are custom options we want to track.
|
|
70
|
-
extra_options = %i[argon2 mails kitchen_sink defaults]
|
|
71
|
-
# Append them to all the available options from our configuration
|
|
72
|
-
valid_options = configuration.keys.map(&:to_sym).concat extra_options
|
|
73
|
-
# Index map the list with the selection value
|
|
74
|
-
opts = valid_options.map { |opt| [opt, send(:"#{opt}?")] }.to_h.compact
|
|
75
|
-
# True only options. We don't care if they are false.
|
|
76
|
-
%i[api_only force skip pretend quiet].each do |key|
|
|
77
|
-
next unless options[key]
|
|
78
|
-
|
|
79
|
-
opts[key] = options[key]
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
opts
|
|
83
|
-
end
|
|
84
|
-
|
|
85
67
|
def all_selected
|
|
86
68
|
@all_selected ||= configuration.keys.select { |feature| send(:"#{feature}?") }
|
|
87
69
|
end
|
|
@@ -6,11 +6,34 @@ module Plutonium
|
|
|
6
6
|
module Action
|
|
7
7
|
# Base class for all actions in the Plutonium framework.
|
|
8
8
|
class Base
|
|
9
|
-
attr_reader :name, :
|
|
9
|
+
attr_reader :name, :icon, :route_options, :turbo, :color, :category, :position, :return_to, :condition, :link, :button
|
|
10
|
+
|
|
11
|
+
# `label:`, `description:` and `confirmation:` may be lazy translations
|
|
12
|
+
# (`t(...)` in a definition) or any zero-arity proc: resolve per read so
|
|
13
|
+
# the text follows the request locale rather than the class load.
|
|
14
|
+
def label
|
|
15
|
+
Plutonium::Translation.resolve(@label) ||
|
|
16
|
+
Plutonium::Translation.label_for(:action, @resource_class, @name) ||
|
|
17
|
+
@name.to_s.titleize
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def description = Plutonium::Translation.resolve(@description)
|
|
21
|
+
|
|
22
|
+
# A copy of this action bound to `resource_class`, so its default label
|
|
23
|
+
# resolves through plutonium.actions.<model>.<action>. Returns self when
|
|
24
|
+
# already bound.
|
|
25
|
+
def for_resource(resource_class)
|
|
26
|
+
return self if @resource_class || resource_class.nil?
|
|
27
|
+
|
|
28
|
+
dup.tap { |copy| copy.instance_variable_set(:@resource_class, resource_class) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def confirmation = Plutonium::Translation.resolve(@confirmation)
|
|
10
32
|
|
|
11
33
|
def initialize(name, **options)
|
|
12
34
|
@name = name.to_sym
|
|
13
|
-
@label = options[:label]
|
|
35
|
+
@label = options[:label]
|
|
36
|
+
@resource_class = options[:resource_class]
|
|
14
37
|
@description = options[:description]
|
|
15
38
|
@icon = options[:icon] || Phlex::TablerIcons::ChevronRight
|
|
16
39
|
@color = options[:color]
|
|
@@ -152,7 +175,8 @@ module Plutonium
|
|
|
152
175
|
size: @modal_size,
|
|
153
176
|
condition: @condition,
|
|
154
177
|
link: @link,
|
|
155
|
-
button: @button
|
|
178
|
+
button: @button,
|
|
179
|
+
resource_class: @resource_class
|
|
156
180
|
}
|
|
157
181
|
end
|
|
158
182
|
|