poetry-jumpstart_pro 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +14 -0
- data/LICENSE.txt +21 -0
- data/README.md +119 -0
- data/lib/generators/poetry_jumpstart_pro/install/files/poetry_jumpstart_pro_helper.rb +41 -0
- data/lib/generators/poetry_jumpstart_pro/install/install_generator.rb +196 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/account/passwords/edit.html.erb +46 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/account_invitations/show.html.erb +29 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/account_users/_form.html.erb +20 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/account_users/edit.html.erb +34 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/_form.html.erb +26 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/account_invitations/edit.html.erb +49 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/account_invitations/new.html.erb +37 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/edit.html.erb +51 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/index.html.erb +56 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/new.html.erb +18 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/show.html.erb +102 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/accounts/transfers/_form.html.erb +30 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/application/_account_navbar.html.erb +40 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/announcements/announcements/_announcement.html.erb +28 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/announcements/announcements/index.html.erb +50 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/announcements/announcements/show.html.erb +32 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/_form.html.erb +39 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/edit.html.erb +16 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/index.html.erb +48 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/new.html.erb +15 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/show.html.erb +69 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/application/_error_messages.html.erb +17 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/passwords/edit.html.erb +23 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/passwords/new.html.erb +26 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/registrations/edit.html.erb +103 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/registrations/new.html.erb +55 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/sessions/new.html.erb +39 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/sessions/otps/new.html.erb +24 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/shared/_oauth.html.erb +22 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/sudo/new.html.erb +31 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/auth/users/two_factor/verify.html.erb +53 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/_charges.html.erb +45 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/_email.html.erb +15 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/_info.html.erb +30 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/show.html.erb +26 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/_plan.html.erb +33 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/_subscription.html.erb +74 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/_summary.html.erb +21 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/cancels/show.html.erb +46 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/edit.html.erb +65 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/paddle_billing/edit.html.erb +17 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/payment_methods/forms/_fake_processor.html.erb +6 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/payment_methods/new.html.erb +26 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/resumes/show.html.erb +29 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/billing/subscriptions/upcomings/show.html.erb +67 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/billing/pricing/show.html.erb +61 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/checkouts/checkouts/_testimonial.html.erb +15 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/checkouts/checkouts/show.html.erb +125 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/dashboard/dashboard/show.html.erb +60 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/errors/errors/404.html.erb +12 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/errors/errors/500.html.erb +12 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/errors/errors/show.html.erb +16 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/madmin/madmin/dashboard/show.html.erb +40 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/madmin/madmin/fields/array_field/_form.html.erb +29 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/madmin/madmin/fields/array_field/_index.html.erb +13 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/madmin/madmin/fields/array_field/_show.html.erb +13 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/notifications/notifications/_notification.html.erb +12 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/notifications/notifications/index.html.erb +31 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/notifications/notifications/nav.html.erb +17 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/public/public/about.html.erb +32 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/public/public/index.html.erb +71 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/public/public/privacy.html.erb +37 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/public/public/terms.html.erb +37 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_account_menu.html.erb +41 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_dev_menu.html.erb +13 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_flash.html.erb +37 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_footer.html.erb +18 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_left_nav.html.erb +11 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_navbar.html+native.erb +36 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_navbar.html.erb +32 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_notifications.html.erb +26 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_right_nav.html.erb +6 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/shell/application/_user_menu.html.erb +34 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/users/users/_user.html.erb +9 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/users/users/agreements/show.html.erb +33 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/users/users/connected_accounts/_connected_account.html.erb +25 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/users/users/connected_accounts/index.html.erb +34 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/users/users/referrals/index.html.erb +49 -0
- data/lib/generators/poetry_jumpstart_pro/install/templates/users/users/two_factor/backup_codes.html.erb +32 -0
- data/lib/poetry/jumpstart_pro/css_scanner.rb +121 -0
- data/lib/poetry/jumpstart_pro/engine.rb +15 -0
- data/lib/poetry/jumpstart_pro/stylesheets.rb +155 -0
- data/lib/poetry/jumpstart_pro/test_edits.rb +51 -0
- data/lib/poetry/jumpstart_pro/version.rb +8 -0
- data/lib/poetry/jumpstart_pro.rb +43 -0
- metadata +194 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1c9e81c6db2c0850dbeb6a11e2d85879803a326ac4d6f558efa04580f2e96943
|
|
4
|
+
data.tar.gz: ff13db73aa4ff09caee3fa89a932f68a56a84898e11d16df2b76d1527ec4739e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 49d3be69c1e975012e5ebd8e141f7b0e376e3da8e136038b5a0b6e345dc81a39a6641b1217d9306af3717263c6dcb7cb538da799973009a071784d24174d2171
|
|
7
|
+
data.tar.gz: deb4930e9b3063b62e0111acc4cd24371d9079769cb73ce9f36145c05798d26e660c5c6648fe86222adc67044215f2620df116273cb553f4f736001a5ae497f5
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [0.1.12] - 2026-10-07
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- First release. `bin/rails g poetry_jumpstart_pro:install` re-skins a Jumpstart Pro app on Rails 8 authentication with Poetry: seventy-nine view recreations in thirteen categories (auth, shell, accounts, users, api_tokens, notifications, announcements, checkouts, public, dashboard, errors, billing, madmin) install as `app/views` overrides, which Rails resolves ahead of the Jumpstart engine's originals. The checkout processor forms, the Braintree and PayPal payment method forms, the agreement content partials and the mention list stay Jumpstart's.
|
|
12
|
+
- The generator runs `poetry:install` when the app has no Poetry yet; reconciles Jumpstart's stylesheets with Poetry's (the forms plugin's class strategy, the primary and background tokens, the bare `a`, `ul` and `ol` rules, and heading, `code` and `kbd` rules that skip Poetry's components); installs `app/helpers/poetry_jumpstart_pro_helper.rb`, the pagination and toast adapters; adds the app stylesheet to Madmin; and updates the selectors in Jumpstart's own sign in, two-factor and pagination tests.
|
|
13
|
+
- Jumpstart's untouched development-boot copies of its default views are replaced without a prompt, and an edited copy prompts like any generator conflict. Every step is idempotent, so a re-run after an upgrade is safe.
|
|
14
|
+
- Options: `--theme`, `--skip-poetry-install`, `--skip-stylesheets` and `--skip-tests`, beside the usual generator flags.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matt Solt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# poetry-jumpstart_pro
|
|
2
|
+
|
|
3
|
+
Re-skin a [Jumpstart Pro](https://jumpstartrails.com) app with
|
|
4
|
+
[Poetry](https://github.com/roboruby/poetry) components: accessible,
|
|
5
|
+
themeable from one design source, and agent-legible.
|
|
6
|
+
|
|
7
|
+
> **License note.** Jumpstart Pro is commercial. This gem ships **only
|
|
8
|
+
> Poetry-native recreations** of the screens (created with the Jumpstart Pro
|
|
9
|
+
> author's explicit permission), never Jumpstart's source. It installs them as
|
|
10
|
+
> **host `app/views/` overrides**, which Rails resolves ahead of the Jumpstart
|
|
11
|
+
> engine's originals, so your licensed Jumpstart source is never touched.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- Jumpstart Pro on Rails 8 authentication (the `users/*` sign in screens).
|
|
16
|
+
- Poetry at the same version as this gem (`gem "poetry"`; the family releases in lockstep), Ruby 3.4 or later.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
# Gemfile (in your Jumpstart Pro app)
|
|
22
|
+
gem "poetry"
|
|
23
|
+
gem "poetry-jumpstart_pro", group: :development
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
bundle install
|
|
28
|
+
bin/rails g poetry_jumpstart_pro:install # every category; runs poetry:install if needed
|
|
29
|
+
bin/rails tailwindcss:build
|
|
30
|
+
bin/rails poetry:check
|
|
31
|
+
bin/rails test && bin/rails test:system
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Pass category names to install a subset (`bin/rails g
|
|
35
|
+
poetry_jumpstart_pro:install auth shell`). Every installed file is yours to
|
|
36
|
+
edit; delete an override to fall back to Jumpstart's view. Re-running is
|
|
37
|
+
safe: identical files are skipped and every edit below is idempotent.
|
|
38
|
+
|
|
39
|
+
## What the installer does
|
|
40
|
+
|
|
41
|
+
1. **Reconciles the stylesheets.** Jumpstart's CSS declares a few things
|
|
42
|
+
globally that would win over Poetry's tokens and components. The forms
|
|
43
|
+
plugin moves to the class strategy, Jumpstart's `--color-primary` mapping
|
|
44
|
+
and `--background` declarations give way to Poetry's tokens, the bare
|
|
45
|
+
`a`, `ul` and `ol` rules leave `components/base.css`, and the bare heading,
|
|
46
|
+
`code` and `kbd` rules in `components/typography.css` skip Poetry's
|
|
47
|
+
components (elements with `data-slot`).
|
|
48
|
+
2. **Installs Poetry** with `bin/rails g poetry:install` when the app has no
|
|
49
|
+
Poetry tokens yet (`--theme` picks the theme).
|
|
50
|
+
3. **Copies the views** for each category into `app/views/`. In development
|
|
51
|
+
Jumpstart copies a few default views into `app/views/` on boot (the
|
|
52
|
+
layout, `_head`, the left and right nav, the dashboard, the landing and
|
|
53
|
+
about pages, the agreements); an untouched copy is replaced without a
|
|
54
|
+
prompt, an edited one prompts like any Rails generator conflict.
|
|
55
|
+
4. **Adds `app/helpers/poetry_jumpstart_pro_helper.rb`**:
|
|
56
|
+
`poetry_pagination_nav(@page)` draws Jumpstart's pagination page as
|
|
57
|
+
`poetry_pagination`, and `poetry_toast_variant` maps Jumpstart's toast
|
|
58
|
+
icons onto Poetry's toast variants.
|
|
59
|
+
5. **Styles the admin** (madmin category): `Madmin.stylesheets << "tailwind"`
|
|
60
|
+
in `config/initializers/madmin.rb`.
|
|
61
|
+
6. **Updates Jumpstart's own tests** that assert on replaced markup: the sign
|
|
62
|
+
in helpers click `[name="commit"]` (Poetry's submit is a button), and the
|
|
63
|
+
pagination test reads Poetry's `nav[aria-label=pagination]`.
|
|
64
|
+
|
|
65
|
+
The layouts stay Jumpstart's. The page's one `poetry_toaster` lives in the
|
|
66
|
+
flash partial, which every Jumpstart layout renders once.
|
|
67
|
+
|
|
68
|
+
Options: `--skip-stylesheets`, `--skip-tests`, `--skip-poetry-install`,
|
|
69
|
+
`--theme NAME`, plus the usual generator flags (`--force`, `--skip`,
|
|
70
|
+
`--pretend`).
|
|
71
|
+
|
|
72
|
+
## Categories
|
|
73
|
+
|
|
74
|
+
| Category | Screens |
|
|
75
|
+
|----------|---------|
|
|
76
|
+
| `auth` | Sign in, two-factor challenge, sign up, profile, password reset, sudo, OAuth buttons, form errors |
|
|
77
|
+
| `shell` | Navbar and its Hotwire Native variant, left and right nav, account, user and dev menus, notifications, flash and toaster, footer |
|
|
78
|
+
| `accounts` | Accounts index, show, new, edit and form, members, invitations, transfer, account password, the settings navigation |
|
|
79
|
+
| `users` | Mention chip, agreements, connected accounts, referrals, two-factor backup codes |
|
|
80
|
+
| `api_tokens` | API tokens index, show, new, edit and form |
|
|
81
|
+
| `notifications` | Notifications index, the navbar panel and the row |
|
|
82
|
+
| `announcements` | Announcements index, show and the row |
|
|
83
|
+
| `checkouts` | The checkout page and its testimonial |
|
|
84
|
+
| `public` | Landing, about, privacy, terms |
|
|
85
|
+
| `dashboard` | The signed-in home |
|
|
86
|
+
| `errors` | 404, 500 and the generic error page |
|
|
87
|
+
| `billing` | Billing overview, email, info, charges, subscriptions (plan, summary, change, cancel, resume, upcoming, payment method), pricing |
|
|
88
|
+
| `madmin` | Admin dashboard and the array field |
|
|
89
|
+
|
|
90
|
+
Seventy-nine templates in all. Some views stay Jumpstart's because they
|
|
91
|
+
cannot be recreated without copying: the checkout processor forms, the
|
|
92
|
+
Braintree and PayPal payment method forms, the agreement content partials
|
|
93
|
+
and the mention list.
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bundle install
|
|
99
|
+
bundle exec rake
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The suite validates the generator, the stylesheet and test edits, and the
|
|
103
|
+
templates. Point it at your own licensed Jumpstart Pro checkout to add the
|
|
104
|
+
drift guard (every template shadows a view the engine ships), the license
|
|
105
|
+
guard (no template is a near copy of its original) and the translation check
|
|
106
|
+
(every key without a default exists in Jumpstart's English locale):
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
JUMPSTART_PRO_PATH=/path/to/jumpstart-pro-rails bundle exec rake
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Those checks skip cleanly when the variable is unset. The Jumpstart repo is
|
|
113
|
+
never copied into or committed to this project.
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
Available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
118
|
+
The license covers the Poetry recreations this gem ships; it does not
|
|
119
|
+
contain (and grants no rights to) Jumpstart Pro's own source.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Installed by `bin/rails g poetry_jumpstart_pro:install` - this file is
|
|
4
|
+
# yours: edit freely.
|
|
5
|
+
#
|
|
6
|
+
# The two adapters the Poetry views lean on: Jumpstart's pagination page
|
|
7
|
+
# drawn as poetry_pagination, and Jumpstart's toast icons mapped onto
|
|
8
|
+
# Poetry's toast variants.
|
|
9
|
+
module PoetryJumpstartProHelper
|
|
10
|
+
# Jumpstart toasts name an icon (alert, notice, success); Poetry toasts
|
|
11
|
+
# carry the intent as a variant, which also picks the icon.
|
|
12
|
+
TOAST_VARIANTS = {
|
|
13
|
+
"alert" => :destructive,
|
|
14
|
+
"notice" => :info,
|
|
15
|
+
"success" => :success
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
# The Poetry pagination for a Jumpstart Pagination::Page, the @page a
|
|
19
|
+
# controller's paginate call sets. Renders nothing at a single page and
|
|
20
|
+
# keeps every other query param, through Jumpstart's pagination_path.
|
|
21
|
+
# Any other keywords (the siblings: and edges: window, attributes for the
|
|
22
|
+
# nav) pass through to poetry_pagination.
|
|
23
|
+
#
|
|
24
|
+
# <%= poetry_pagination_nav(@page) %>
|
|
25
|
+
#
|
|
26
|
+
# @param page [Pagination::Page] the page object
|
|
27
|
+
def poetry_pagination_nav(page, **)
|
|
28
|
+
return "".html_safe unless page.multiple_pages?
|
|
29
|
+
|
|
30
|
+
poetry_pagination(current: page.number, total: page.total_pages,
|
|
31
|
+
path: ->(number) { pagination_path(page, number) }, **)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The Poetry toast variant for a Jumpstart toast's icon_name.
|
|
35
|
+
#
|
|
36
|
+
# @param icon_name [String, Symbol, nil] the toast's icon name
|
|
37
|
+
# @return [Symbol] the Poetry toast variant
|
|
38
|
+
def poetry_toast_variant(icon_name)
|
|
39
|
+
TOAST_VARIANTS.fetch(icon_name.to_s, :default)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "poetry/jumpstart_pro"
|
|
5
|
+
|
|
6
|
+
module PoetryJumpstartPro
|
|
7
|
+
# `rails g poetry_jumpstart_pro:install [categories...]`
|
|
8
|
+
#
|
|
9
|
+
# Re-skins a Jumpstart Pro app with Poetry. It copies Poetry recreations of
|
|
10
|
+
# Jumpstart's views into the host's app/views/, where Rails resolves them
|
|
11
|
+
# ahead of the Jumpstart engine's originals, then wires what those views
|
|
12
|
+
# lean on:
|
|
13
|
+
#
|
|
14
|
+
# - the stylesheet reconciliation (Poetry::JumpstartPro::Stylesheets),
|
|
15
|
+
# so Jumpstart's global CSS stops overriding Poetry's components
|
|
16
|
+
# - Poetry itself (`poetry:install`) when the app does not have it yet
|
|
17
|
+
# - app/helpers/poetry_jumpstart_pro_helper.rb, the pagination and toast
|
|
18
|
+
# adapters
|
|
19
|
+
# - Poetry's styles on the Madmin pages, with the madmin category
|
|
20
|
+
# - the selectors of Jumpstart's own tests that assert on the replaced
|
|
21
|
+
# markup (Poetry::JumpstartPro::TestEdits)
|
|
22
|
+
#
|
|
23
|
+
# Views are verbatim copies (copy_file, never template), so the ERB is the
|
|
24
|
+
# exact runtime view. In development Jumpstart copies a few default views
|
|
25
|
+
# into app/views on boot (the layout, _head, the left and right nav, the
|
|
26
|
+
# dashboard, the landing and about pages, the agreements); a copy still
|
|
27
|
+
# identical to the engine's view is replaced without asking, and one the
|
|
28
|
+
# app has edited prompts like any Rails generator conflict. Every step is
|
|
29
|
+
# idempotent, so re-running after an upgrade is safe.
|
|
30
|
+
#
|
|
31
|
+
# @example Install every category
|
|
32
|
+
# rails g poetry_jumpstart_pro:install
|
|
33
|
+
# @example Install the sign in screens and the app shell only
|
|
34
|
+
# rails g poetry_jumpstart_pro:install auth shell
|
|
35
|
+
class InstallGenerator < Rails::Generators::Base
|
|
36
|
+
source_root File.expand_path("templates", __dir__)
|
|
37
|
+
|
|
38
|
+
# The host helper the views call, copied once and then the host's own.
|
|
39
|
+
HELPER = File.expand_path("files/poetry_jumpstart_pro_helper.rb", __dir__)
|
|
40
|
+
|
|
41
|
+
# The file whose presence means `poetry:install` has run.
|
|
42
|
+
POETRY_TOKENS = "app/assets/tailwind/poetry/tokens.css"
|
|
43
|
+
# The Tailwind entry, which imports the tokens once the install finished.
|
|
44
|
+
TAILWIND_ENTRY = "app/assets/tailwind/application.css"
|
|
45
|
+
# Where a Jumpstart Pro app keeps the engine's own views.
|
|
46
|
+
ENGINE_VIEWS = "lib/jumpstart/app/views"
|
|
47
|
+
|
|
48
|
+
# Madmin's initializer and the line that adds the app stylesheet to it.
|
|
49
|
+
MADMIN_INITIALIZER = "config/initializers/madmin.rb"
|
|
50
|
+
# Appended to the Madmin initializer for the madmin category.
|
|
51
|
+
MADMIN_STYLESHEET = %(Madmin.stylesheets << "tailwind")
|
|
52
|
+
|
|
53
|
+
argument :categories, type: :array, default: Poetry::JumpstartPro::CATEGORIES,
|
|
54
|
+
banner: "category ..."
|
|
55
|
+
|
|
56
|
+
class_option :theme, type: :string, default: nil,
|
|
57
|
+
desc: "The Poetry theme for `poetry:install` when Poetry is not installed yet"
|
|
58
|
+
class_option :skip_poetry_install, type: :boolean, default: false,
|
|
59
|
+
desc: "Do not run `poetry:install`, even when Poetry is missing"
|
|
60
|
+
class_option :skip_stylesheets, type: :boolean, default: false,
|
|
61
|
+
desc: "Leave Jumpstart's stylesheets untouched"
|
|
62
|
+
class_option :skip_tests, type: :boolean, default: false,
|
|
63
|
+
desc: "Leave the selectors in Jumpstart's own tests untouched"
|
|
64
|
+
|
|
65
|
+
desc "Re-skin a Jumpstart Pro app's views with Poetry components"
|
|
66
|
+
|
|
67
|
+
# Step: reconciles Jumpstart's stylesheets with Poetry's, before
|
|
68
|
+
# `poetry:install` so its token report starts from the reconciled files
|
|
69
|
+
# (Thor task).
|
|
70
|
+
# @api private
|
|
71
|
+
def reconcile_stylesheets
|
|
72
|
+
return if installed.empty? || options[:skip_stylesheets]
|
|
73
|
+
|
|
74
|
+
Poetry::JumpstartPro::Stylesheets::FILES.each do |relative, edit|
|
|
75
|
+
path = File.join(destination_root, relative)
|
|
76
|
+
next say_status(:missing, relative, :yellow) unless File.exist?(path)
|
|
77
|
+
|
|
78
|
+
before = File.read(path)
|
|
79
|
+
after = Poetry::JumpstartPro::Stylesheets.public_send(edit, before)
|
|
80
|
+
next say_status(:identical, relative, :blue) if after == before
|
|
81
|
+
|
|
82
|
+
File.write(path, after) unless options[:pretend]
|
|
83
|
+
say_status :reconcile, relative, :green
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Step: runs `poetry:install` when the app has no Poetry yet (Thor task).
|
|
88
|
+
# @api private
|
|
89
|
+
def install_poetry
|
|
90
|
+
return if poetry_installed?
|
|
91
|
+
|
|
92
|
+
theme = options[:theme] ? ["--theme", options[:theme]] : []
|
|
93
|
+
return generate("poetry:install", *theme) unless options[:skip_poetry_install]
|
|
94
|
+
|
|
95
|
+
say_status :poetry, "not installed - run `bin/rails g poetry:install` before using these views", :yellow
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Step: copies each requested category's view overrides (Thor task).
|
|
99
|
+
# @api private
|
|
100
|
+
def install_categories
|
|
101
|
+
categories.each do |category|
|
|
102
|
+
unless Poetry::JumpstartPro::CATEGORIES.include?(category)
|
|
103
|
+
say_status :skip, "unknown category #{category.inspect} " \
|
|
104
|
+
"(available: #{Poetry::JumpstartPro::CATEGORIES.join(", ")})", :yellow
|
|
105
|
+
next
|
|
106
|
+
end
|
|
107
|
+
copy_category(category)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Step: copies the pagination and toast adapters the views call (Thor task).
|
|
112
|
+
# @api private
|
|
113
|
+
def install_helper
|
|
114
|
+
return if installed.empty?
|
|
115
|
+
|
|
116
|
+
copy_file HELPER, "app/helpers/poetry_jumpstart_pro_helper.rb"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Step: adds the app stylesheet to Madmin's pages, for the madmin
|
|
120
|
+
# category (Thor task).
|
|
121
|
+
# @api private
|
|
122
|
+
def style_madmin
|
|
123
|
+
return unless installed.include?("madmin")
|
|
124
|
+
|
|
125
|
+
path = File.join(destination_root, MADMIN_INITIALIZER)
|
|
126
|
+
return say_status(:missing, MADMIN_INITIALIZER, :yellow) unless File.exist?(path)
|
|
127
|
+
return say_status(:identical, MADMIN_INITIALIZER, :blue) if File.read(path).include?(MADMIN_STYLESHEET)
|
|
128
|
+
|
|
129
|
+
append_to_file MADMIN_INITIALIZER,
|
|
130
|
+
"\n# Poetry's styles on the admin pages poetry-jumpstart_pro re-skinned.\n#{MADMIN_STYLESHEET}\n"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Step: updates the selectors in Jumpstart's own tests that assert on the
|
|
134
|
+
# markup the installed views replace (Thor task).
|
|
135
|
+
# @api private
|
|
136
|
+
def update_tests
|
|
137
|
+
return if options[:skip_tests]
|
|
138
|
+
|
|
139
|
+
Poetry::JumpstartPro::TestEdits.for(installed).each do |edit|
|
|
140
|
+
path = File.join(destination_root, edit.file)
|
|
141
|
+
next unless File.exist?(path) && edit.applies_to?(File.read(path))
|
|
142
|
+
|
|
143
|
+
gsub_file edit.file, edit.pattern, edit.replacement
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Step: prints the post-install checklist (Thor task).
|
|
148
|
+
# @api private
|
|
149
|
+
def next_steps
|
|
150
|
+
return if installed.empty?
|
|
151
|
+
|
|
152
|
+
say ""
|
|
153
|
+
say "poetry-jumpstart_pro installed #{installed.join(", ")} as overrides in app/views/.", :green
|
|
154
|
+
say " 1. Rebuild the CSS: bin/rails tailwindcss:build"
|
|
155
|
+
say " 2. Check the views: bin/rails poetry:check"
|
|
156
|
+
say " 3. Run your tests: bin/rails test && bin/rails test:system"
|
|
157
|
+
say "Every installed file is yours to edit. Delete an override to fall back to Jumpstart's view."
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
private
|
|
161
|
+
|
|
162
|
+
# The requested categories this gem knows.
|
|
163
|
+
def installed
|
|
164
|
+
categories & Poetry::JumpstartPro::CATEGORIES
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Whether `poetry:install` has run to the end in the host: the tokens
|
|
168
|
+
# are vendored and the Tailwind entry imports them.
|
|
169
|
+
def poetry_installed?
|
|
170
|
+
entry = File.join(destination_root, TAILWIND_ENTRY)
|
|
171
|
+
File.exist?(File.join(destination_root, POETRY_TOKENS)) &&
|
|
172
|
+
File.exist?(entry) && File.read(entry).include?("poetry/tokens.css")
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Whether the host's copy of a view is Jumpstart's default, unedited: the
|
|
176
|
+
# file the engine copies in on a development boot.
|
|
177
|
+
def jumpstart_default?(view)
|
|
178
|
+
host = File.join(destination_root, view)
|
|
179
|
+
original = File.join(destination_root, ENGINE_VIEWS, view.delete_prefix("app/views/"))
|
|
180
|
+
File.exist?(host) && File.exist?(original) && File.binread(host) == File.binread(original)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Mirror templates/<category>/**/* onto app/views/**/*, stripping the
|
|
184
|
+
# category prefix (the template tree already mirrors the view tree).
|
|
185
|
+
def copy_category(category)
|
|
186
|
+
base = File.join(self.class.source_root, category)
|
|
187
|
+
Dir.glob("#{base}/**/*").select { |path| File.file?(path) }.sort.each do |source|
|
|
188
|
+
relative = source.delete_prefix("#{base}/")
|
|
189
|
+
view = File.join("app/views", relative)
|
|
190
|
+
# Only ever force: an explicit false would override a --force given
|
|
191
|
+
# on the command line, since Thor merges this over the options.
|
|
192
|
+
copy_file File.join(category, relative), view, **(jumpstart_default?(view) ? { force: true } : {})
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/account/passwords/edit.html.erb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's account/passwords/edit: the password
|
|
2
|
+
change form on the Poetry builder (password fields never round-trip),
|
|
3
|
+
then two-factor authentication - enabling navigates to the backup codes,
|
|
4
|
+
disabling confirms in an AlertDialog that submits the DELETE form. %>
|
|
5
|
+
<% content_for :title, t(".title") %>
|
|
6
|
+
|
|
7
|
+
<header class="flex flex-col gap-4">
|
|
8
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
9
|
+
<%= poetry_separator %>
|
|
10
|
+
</header>
|
|
11
|
+
|
|
12
|
+
<%= form_with(model: current_user, url: account_password_path, method: :put, builder: Poetry::Ui::FormBuilder, class: "mt-6 max-w-md space-y-6") do |form| %>
|
|
13
|
+
<%= render "application/error_messages", resource: current_user %>
|
|
14
|
+
|
|
15
|
+
<%= form.group do %>
|
|
16
|
+
<%= form.password_field :password_challenge, autocomplete: "current-password", hint: t("users.registrations.edit.we_need_your_current_password_to_confirm_your_changes") %>
|
|
17
|
+
<%= form.password_field :password, autocomplete: "new-password", hint: t("users.shared.minimum_password_length", count: User::MINIMUM_PASSWORD_LENGTH) %>
|
|
18
|
+
<%= form.password_field :password_confirmation, autocomplete: "new-password" %>
|
|
19
|
+
<% end %>
|
|
20
|
+
|
|
21
|
+
<div>
|
|
22
|
+
<%= form.submit t(".update") %>
|
|
23
|
+
</div>
|
|
24
|
+
<% end %>
|
|
25
|
+
|
|
26
|
+
<%= poetry_separator(class: "my-10") %>
|
|
27
|
+
|
|
28
|
+
<section class="space-y-4" aria-labelledby="two-factor-title">
|
|
29
|
+
<div class="space-y-1">
|
|
30
|
+
<h2 id="two-factor-title" class="text-lg font-semibold"><%= t(".two_factor.title") %></h2>
|
|
31
|
+
<p class="text-sm text-muted-foreground"><%= t(".two_factor.description") %></p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<% if current_user.otp_required_for_login? %>
|
|
35
|
+
<%= form_with(url: user_two_factor_path, method: :delete, id: "disable-two-factor-form", class: "hidden") {} %>
|
|
36
|
+
<%= poetry_alert_dialog do |dialog| %>
|
|
37
|
+
<% dialog.with_trigger(variant: :outline, class: "text-destructive") { t(".two_factor.disable") } %>
|
|
38
|
+
<% dialog.with_title { t(".two_factor.disable") } %>
|
|
39
|
+
<% dialog.with_description { t("are_you_sure") } %>
|
|
40
|
+
<% dialog.with_cancel { t("cancel") } %>
|
|
41
|
+
<% dialog.with_action(variant: :destructive, submit: "disable-two-factor-form") { t(".two_factor.disable") } %>
|
|
42
|
+
<% end %>
|
|
43
|
+
<% else %>
|
|
44
|
+
<%= poetry_button(href: backup_codes_user_two_factor_path, variant: :outline) { t(".two_factor.enable") } %>
|
|
45
|
+
<% end %>
|
|
46
|
+
</section>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's account_invitations/show (accept or
|
|
2
|
+
decline an invitation): a centered card; Accept submits the PUT form,
|
|
3
|
+
Decline confirms in an AlertDialog that submits the DELETE form. %>
|
|
4
|
+
<% content_for :title, t(".title", account: @account.name) %>
|
|
5
|
+
|
|
6
|
+
<div class="mx-auto w-full max-w-2xl px-4 py-8 lg:px-6">
|
|
7
|
+
<%= poetry_card(title_tag: :h1, class: "mx-auto max-w-md text-center") do |card| %>
|
|
8
|
+
<% card.with_title { t(".title", account: @account.name) } %>
|
|
9
|
+
<% card.with_description { t(".invited_you_to_join_html", inviter: @account_invitation.invited_by.name, account: @account_invitation.account.name) } %>
|
|
10
|
+
|
|
11
|
+
<div class="flex justify-center">
|
|
12
|
+
<%= account_avatar @account, size: "size-16" %>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<% card.with_footer(class: "flex flex-wrap justify-center gap-3") do %>
|
|
16
|
+
<%= form_with(url: account_invitation_path(@account_invitation.token), method: :put) do %>
|
|
17
|
+
<%= poetry_button(type: :submit) { t(".accept") } %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<%= form_with(url: account_invitation_path(@account_invitation.token), method: :delete, id: "decline-invitation-form", class: "hidden") {} %>
|
|
20
|
+
<%= poetry_alert_dialog do |dialog| %>
|
|
21
|
+
<% dialog.with_trigger(variant: :outline) { t(".decline") } %>
|
|
22
|
+
<% dialog.with_title { t(".decline") } %>
|
|
23
|
+
<% dialog.with_description { t("are_you_sure") } %>
|
|
24
|
+
<% dialog.with_cancel { t("cancel") } %>
|
|
25
|
+
<% dialog.with_action(variant: :destructive, submit: "decline-invitation-form") { t(".decline") } %>
|
|
26
|
+
<% end %>
|
|
27
|
+
<% end %>
|
|
28
|
+
<% end %>
|
|
29
|
+
</div>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/account_users/_form.html.erb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's account_users/_form: one checkbox per
|
|
2
|
+
role, each the builder's horizontal Field with its visible label; the
|
|
3
|
+
owner's admin box stays disabled (the same name/disabled contract the
|
|
4
|
+
integration tests assert). %>
|
|
5
|
+
<%= form_with(model: [account_user.account, account_user], builder: Poetry::Ui::FormBuilder, class: "max-w-md space-y-6") do |form| %>
|
|
6
|
+
<%= render "application/error_messages", resource: form.object %>
|
|
7
|
+
|
|
8
|
+
<%= form.fieldset(legend: t("accounts.roles"), legend_variant: :label) do %>
|
|
9
|
+
<%= poetry_field_group(variant: :choices) do %>
|
|
10
|
+
<% AccountUser::ROLES.each do |role| %>
|
|
11
|
+
<%= form.check_box role, label: account_user_role_name(role), disabled: (role == :admin && account_user.account_owner?) %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% end %>
|
|
15
|
+
|
|
16
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
17
|
+
<%= form.submit %>
|
|
18
|
+
<%= poetry_button(href: account_path(account_user.account), variant: :ghost) { t("cancel") } %>
|
|
19
|
+
</div>
|
|
20
|
+
<% end %>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/accounts/account_users/edit.html.erb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's account_users/edit: a member's roles,
|
|
2
|
+
with removal as an AlertDialog that submits the DELETE form it sits in.
|
|
3
|
+
The title key interpolates the member (the engine left %{user} unfilled). %>
|
|
4
|
+
<% user_name = @account_user.user.name || @account_user.user.email %>
|
|
5
|
+
<% content_for :title, t(".title", user: user_name) %>
|
|
6
|
+
|
|
7
|
+
<header class="flex flex-col gap-4">
|
|
8
|
+
<%= poetry_breadcrumb do |crumb| %>
|
|
9
|
+
<% crumb.with_item(t("accounts.index.title"), href: accounts_path) %>
|
|
10
|
+
<% crumb.with_item(@account.name, href: account_path(@account)) %>
|
|
11
|
+
<% crumb.with_item(user_name) %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<div class="flex flex-wrap items-start justify-between gap-4">
|
|
14
|
+
<div class="space-y-1">
|
|
15
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title", user: user_name) %></h1>
|
|
16
|
+
<p class="text-sm text-muted-foreground"><%= t(".description", user: user_name) %></p>
|
|
17
|
+
</div>
|
|
18
|
+
<% unless @account_user.account_owner? %>
|
|
19
|
+
<%= form_with(url: account_account_user_path(@account, @account_user), method: :delete, id: "remove-member-form", class: "hidden") {} %>
|
|
20
|
+
<%= poetry_alert_dialog do |dialog| %>
|
|
21
|
+
<% dialog.with_trigger(variant: :outline, class: "text-destructive") { t("delete") } %>
|
|
22
|
+
<% dialog.with_title { t("are_you_sure") } %>
|
|
23
|
+
<% dialog.with_description { t(".remove_description", default: "%{user} will lose access to %{account}.", user: user_name, account: @account.name) } %>
|
|
24
|
+
<% dialog.with_cancel { t("cancel") } %>
|
|
25
|
+
<% dialog.with_action(variant: :destructive, submit: "remove-member-form") { t("delete") } %>
|
|
26
|
+
<% end %>
|
|
27
|
+
<% end %>
|
|
28
|
+
</div>
|
|
29
|
+
<%= poetry_separator %>
|
|
30
|
+
</header>
|
|
31
|
+
|
|
32
|
+
<div class="mt-6">
|
|
33
|
+
<%= render "account_users/form", account_user: @account_user %>
|
|
34
|
+
</div>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/_form on the Poetry form
|
|
2
|
+
builder: labels, values, errors and aria-required derive from the
|
|
3
|
+
model; the avatar upload only exists once the account is persisted. %>
|
|
4
|
+
<%= form_with(model: account, builder: Poetry::Ui::FormBuilder, class: "max-w-md space-y-6") do |form| %>
|
|
5
|
+
<%= render "application/error_messages", resource: form.object %>
|
|
6
|
+
|
|
7
|
+
<%= form.group do %>
|
|
8
|
+
<%= form.input :name, label: t("helpers.label.account.name"), placeholder: t("helpers.placeholder.account.name"), autofocus: true %>
|
|
9
|
+
<%= form.input :domain, placeholder: t("helpers.placeholder.account.domain") if Jumpstart::Multitenancy.domain? %>
|
|
10
|
+
<%= form.input :subdomain, placeholder: t("helpers.placeholder.account.subdomain") if Jumpstart::Multitenancy.subdomain? %>
|
|
11
|
+
|
|
12
|
+
<% if form.object.persisted? %>
|
|
13
|
+
<div class="flex items-center gap-4">
|
|
14
|
+
<%= account_avatar form.object, size: "size-12" %>
|
|
15
|
+
<div class="min-w-0 flex-1">
|
|
16
|
+
<%= form.file_input :avatar, accept: "image/png, image/jpeg, image/heic, image/heif, image/webp" %>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
21
|
+
|
|
22
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
23
|
+
<%= form.submit %>
|
|
24
|
+
<%= poetry_button(href: (form.object.persisted? ? account_path(form.object) : accounts_path), variant: :ghost) { t("cancel") } %>
|
|
25
|
+
</div>
|
|
26
|
+
<% end %>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/account_invitations/edit: the
|
|
2
|
+
invitation form plus a guarded delete (AlertDialog submitting the DELETE
|
|
3
|
+
form it sits in). %>
|
|
4
|
+
<% content_for :title, t(".title") %>
|
|
5
|
+
|
|
6
|
+
<header class="flex flex-col gap-4">
|
|
7
|
+
<%= poetry_breadcrumb do |crumb| %>
|
|
8
|
+
<% crumb.with_item(t("accounts.index.title"), href: accounts_path) %>
|
|
9
|
+
<% crumb.with_item(@account.name, href: account_path(@account)) %>
|
|
10
|
+
<% crumb.with_item(t(".title")) %>
|
|
11
|
+
<% end %>
|
|
12
|
+
<div class="flex flex-wrap items-start justify-between gap-4">
|
|
13
|
+
<div class="space-y-1">
|
|
14
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
15
|
+
<p class="text-sm text-muted-foreground"><%= t(".description") %></p>
|
|
16
|
+
</div>
|
|
17
|
+
<%= form_with(url: account_account_invitation_path(@account, @account_invitation), method: :delete, id: "destroy-invitation-form", class: "hidden") {} %>
|
|
18
|
+
<%= poetry_alert_dialog do |dialog| %>
|
|
19
|
+
<% dialog.with_trigger(variant: :outline, class: "text-destructive") { t(".destroy") } %>
|
|
20
|
+
<% dialog.with_title { t(".destroy") } %>
|
|
21
|
+
<% dialog.with_description { t(".destroy_description", default: "The invitation sent to %{email} will stop working.", email: @account_invitation.email) } %>
|
|
22
|
+
<% dialog.with_cancel { t("cancel") } %>
|
|
23
|
+
<% dialog.with_action(variant: :destructive, submit: "destroy-invitation-form") { t(".destroy") } %>
|
|
24
|
+
<% end %>
|
|
25
|
+
</div>
|
|
26
|
+
<%= poetry_separator %>
|
|
27
|
+
</header>
|
|
28
|
+
|
|
29
|
+
<%= form_with(model: [@account, @account_invitation], builder: Poetry::Ui::FormBuilder, class: "mt-6 max-w-md space-y-6") do |form| %>
|
|
30
|
+
<%= render "application/error_messages", resource: form.object %>
|
|
31
|
+
|
|
32
|
+
<%= form.group do %>
|
|
33
|
+
<%= form.input :name, placeholder: t("helpers.placeholder.account_invitation.name") %>
|
|
34
|
+
<%= form.input :email, placeholder: t("helpers.placeholder.account_invitation.email") %>
|
|
35
|
+
|
|
36
|
+
<%= form.fieldset(legend: t("accounts.roles"), legend_variant: :label) do %>
|
|
37
|
+
<%= poetry_field_group(variant: :choices) do %>
|
|
38
|
+
<% AccountUser::ROLES.each do |role| %>
|
|
39
|
+
<%= form.check_box role, label: account_user_role_name(role) %>
|
|
40
|
+
<% end %>
|
|
41
|
+
<% end %>
|
|
42
|
+
<% end %>
|
|
43
|
+
<% end %>
|
|
44
|
+
|
|
45
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
46
|
+
<%= form.submit t(".update") %>
|
|
47
|
+
<%= poetry_button(href: account_path(@account), variant: :ghost) { t("cancel") } %>
|
|
48
|
+
</div>
|
|
49
|
+
<% end %>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/account_invitations/new. %>
|
|
2
|
+
<% content_for :title, t(".title") %>
|
|
3
|
+
|
|
4
|
+
<header class="flex flex-col gap-4">
|
|
5
|
+
<%= poetry_breadcrumb do |crumb| %>
|
|
6
|
+
<% crumb.with_item(t("accounts.index.title"), href: accounts_path) %>
|
|
7
|
+
<% crumb.with_item(@account.name, href: account_path(@account)) %>
|
|
8
|
+
<% crumb.with_item(t(".title")) %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<div class="space-y-1">
|
|
11
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
12
|
+
<p class="text-sm text-muted-foreground"><%= t(".description") %></p>
|
|
13
|
+
</div>
|
|
14
|
+
<%= poetry_separator %>
|
|
15
|
+
</header>
|
|
16
|
+
|
|
17
|
+
<%= form_with(model: @account_invitation, url: account_account_invitations_path(@account), builder: Poetry::Ui::FormBuilder, class: "mt-6 max-w-md space-y-6") do |form| %>
|
|
18
|
+
<%= render "application/error_messages", resource: form.object %>
|
|
19
|
+
|
|
20
|
+
<%= form.group do %>
|
|
21
|
+
<%= form.input :name, placeholder: t("helpers.placeholder.account_invitation.name"), autofocus: true %>
|
|
22
|
+
<%= form.input :email, placeholder: t("helpers.placeholder.account_invitation.email") %>
|
|
23
|
+
|
|
24
|
+
<%= form.fieldset(legend: t("accounts.roles"), legend_variant: :label) do %>
|
|
25
|
+
<%= poetry_field_group(variant: :choices) do %>
|
|
26
|
+
<% AccountUser::ROLES.each do |role| %>
|
|
27
|
+
<%= form.check_box role, label: account_user_role_name(role) %>
|
|
28
|
+
<% end %>
|
|
29
|
+
<% end %>
|
|
30
|
+
<% end %>
|
|
31
|
+
<% end %>
|
|
32
|
+
|
|
33
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
34
|
+
<%= form.submit t(".send") %>
|
|
35
|
+
<%= poetry_button(href: account_path(@account), variant: :ghost) { t("cancel") } %>
|
|
36
|
+
</div>
|
|
37
|
+
<% end %>
|