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
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/edit: the account form, the
|
|
2
|
+
ownership transfer (owner only) and a guarded delete - an AlertDialog
|
|
3
|
+
whose confirming action submits the DELETE form it sits in, replacing
|
|
4
|
+
Jumpstart's data-turbo-confirm + description pair. %>
|
|
5
|
+
<% content_for :title, t(".title") %>
|
|
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(t(".title")) %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<div class="flex items-center gap-4">
|
|
14
|
+
<%= account_avatar @account, size: "size-10" %>
|
|
15
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
16
|
+
</div>
|
|
17
|
+
<%= poetry_separator %>
|
|
18
|
+
</header>
|
|
19
|
+
|
|
20
|
+
<div class="mt-6 space-y-10">
|
|
21
|
+
<%= render "accounts/form", account: @account %>
|
|
22
|
+
|
|
23
|
+
<% if @account.can_transfer?(current_user) %>
|
|
24
|
+
<%= poetry_separator %>
|
|
25
|
+
<%= render "accounts/transfers/form", account: @account %>
|
|
26
|
+
<% end %>
|
|
27
|
+
|
|
28
|
+
<% unless @account.personal? %>
|
|
29
|
+
<% delete_description = subscribed? ? t(".delete_with_payments_description") : t(".delete_description") %>
|
|
30
|
+
<section class="space-y-4 rounded-lg border border-destructive/50 p-6" aria-labelledby="delete-account-title">
|
|
31
|
+
<div class="space-y-1">
|
|
32
|
+
<h2 id="delete-account-title" class="text-base font-semibold"><%= t(".delete_account", default: "Delete account") %></h2>
|
|
33
|
+
<p class="text-sm text-muted-foreground"><%= delete_description %></p>
|
|
34
|
+
</div>
|
|
35
|
+
<%= poetry_alert(variant: :destructive) do |alert| %>
|
|
36
|
+
<% alert.with_icon(name: :"triangle-alert") %>
|
|
37
|
+
<% alert.with_title { t(".cannot_be_undone", default: "This cannot be undone") } %>
|
|
38
|
+
<% end %>
|
|
39
|
+
<%= form_with(url: account_path(@account), method: :delete, id: "delete-account-form", class: "hidden") {} %>
|
|
40
|
+
<div class="flex justify-end">
|
|
41
|
+
<%= poetry_alert_dialog do |dialog| %>
|
|
42
|
+
<% dialog.with_trigger(variant: :destructive) { t("delete") } %>
|
|
43
|
+
<% dialog.with_title { t("are_you_sure") } %>
|
|
44
|
+
<% dialog.with_description { delete_description } %>
|
|
45
|
+
<% dialog.with_cancel { t("cancel") } %>
|
|
46
|
+
<% dialog.with_action(variant: :destructive, submit: "delete-account-form") { t("delete") } %>
|
|
47
|
+
<% end %>
|
|
48
|
+
</div>
|
|
49
|
+
</section>
|
|
50
|
+
<% end %>
|
|
51
|
+
</div>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/index: the accounts the user
|
|
2
|
+
belongs to as a table, with Jumpstart's switch_account_button (a PATCH
|
|
3
|
+
form outside multitenancy) kept as the switch affordance per row. %>
|
|
4
|
+
<% content_for :title, t(".title") %>
|
|
5
|
+
|
|
6
|
+
<header class="flex flex-wrap items-end justify-between gap-4">
|
|
7
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
8
|
+
<% if Jumpstart.config.team_accounts? %>
|
|
9
|
+
<%= poetry_button(href: new_account_path) do |button| %>
|
|
10
|
+
<% button.with_leading { poetry_icon(name: :plus) } %>
|
|
11
|
+
<%= t(".create") %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% end %>
|
|
14
|
+
</header>
|
|
15
|
+
|
|
16
|
+
<div class="mt-6 overflow-hidden rounded-lg border">
|
|
17
|
+
<%= poetry_table do %>
|
|
18
|
+
<%= poetry_table_caption(class: "sr-only") { t(".title") } %>
|
|
19
|
+
<%= poetry_table_header do %>
|
|
20
|
+
<%= poetry_table_row do %>
|
|
21
|
+
<%= poetry_table_head { Account.model_name.human } %>
|
|
22
|
+
<%= poetry_table_head { t("accounts.users") } %>
|
|
23
|
+
<%= poetry_table_head(class: "text-right") { tag.span(t(".actions", default: "Actions"), class: "sr-only") } %>
|
|
24
|
+
<% end %>
|
|
25
|
+
<% end %>
|
|
26
|
+
<%= poetry_table_body do %>
|
|
27
|
+
<% @accounts.sorted.each do |account| %>
|
|
28
|
+
<%= poetry_table_row do %>
|
|
29
|
+
<%= poetry_table_cell do %>
|
|
30
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
31
|
+
<%= poetry_link(href: account_path(account), underline: :none, class: "inline-flex items-center gap-3 font-medium") do %>
|
|
32
|
+
<%= account_avatar account %>
|
|
33
|
+
<span><%= account.name %></span>
|
|
34
|
+
<% end %>
|
|
35
|
+
<%= poetry_badge(variant: :outline) { t(".personal", default: "Personal") } if account.personal_account_for?(current_user) %>
|
|
36
|
+
</div>
|
|
37
|
+
<% end %>
|
|
38
|
+
<%= poetry_table_cell(class: "text-muted-foreground") { pluralize(account.account_users_count, t(".user")) } %>
|
|
39
|
+
<%= poetry_table_cell(class: "text-right") do %>
|
|
40
|
+
<% if current_account != account %>
|
|
41
|
+
<%= switch_account_button account, label: t(".switch"), class: "text-sm font-medium text-primary underline-offset-4 hover:underline", form_class: "inline-flex justify-end" %>
|
|
42
|
+
<% else %>
|
|
43
|
+
<%= poetry_badge(variant: :outline) { t(".current") } %>
|
|
44
|
+
<% end %>
|
|
45
|
+
<% end %>
|
|
46
|
+
<% end %>
|
|
47
|
+
<% end %>
|
|
48
|
+
<% end %>
|
|
49
|
+
<% end %>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<% if @page.multiple_pages? %>
|
|
53
|
+
<div class="mt-6 flex justify-center">
|
|
54
|
+
<%= poetry_pagination_nav(@page) %>
|
|
55
|
+
</div>
|
|
56
|
+
<% end %>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/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(t(".title")) %>
|
|
8
|
+
<% end %>
|
|
9
|
+
<div class="space-y-1">
|
|
10
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
11
|
+
<p class="text-sm text-muted-foreground"><%= t(".description") %></p>
|
|
12
|
+
</div>
|
|
13
|
+
<%= poetry_separator %>
|
|
14
|
+
</header>
|
|
15
|
+
|
|
16
|
+
<div class="mt-6">
|
|
17
|
+
<%= render "accounts/form", account: @account %>
|
|
18
|
+
</div>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/show: the members and pending
|
|
2
|
+
invitations of an account as one table. Jumpstart's switch_account_button
|
|
3
|
+
and clipboard controller (data-clipboard-text) are kept as-is; @admin
|
|
4
|
+
and @account_users come from the controller. %>
|
|
5
|
+
<% content_for :title, @account.name %>
|
|
6
|
+
|
|
7
|
+
<% initials = ->(text) { text.to_s.split(/[\s@._-]+/).reject(&:blank?).first(2).map { |part| part[0] }.join.upcase } %>
|
|
8
|
+
|
|
9
|
+
<header class="flex flex-col gap-4">
|
|
10
|
+
<div class="flex flex-wrap items-center justify-between gap-4">
|
|
11
|
+
<div class="flex items-center gap-4">
|
|
12
|
+
<%= account_avatar @account, size: "size-10" %>
|
|
13
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= @account.name %></h1>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
17
|
+
<%= switch_account_button @account, label: t(".switch"), class: "text-sm font-medium text-primary underline-offset-4 hover:underline", form_class: "inline-flex" unless current_account == @account %>
|
|
18
|
+
<% if !@account.personal? && @admin %>
|
|
19
|
+
<%= poetry_button(href: edit_account_path(@account), variant: :outline) { t(".edit_account") } %>
|
|
20
|
+
<%= poetry_button(href: new_account_account_invitation_path(@account)) do |button| %>
|
|
21
|
+
<% button.with_leading { poetry_icon(name: :"user-plus") } %>
|
|
22
|
+
<%= t(".invite") %>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% end %>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
<%= poetry_separator %>
|
|
28
|
+
</header>
|
|
29
|
+
|
|
30
|
+
<% if @account.personal? %>
|
|
31
|
+
<%= poetry_alert(class: "mt-6") do |alert| %>
|
|
32
|
+
<% alert.with_icon(name: :info) %>
|
|
33
|
+
<%= t(".personal_team_description") %>
|
|
34
|
+
<% end %>
|
|
35
|
+
<% else %>
|
|
36
|
+
<div class="mt-6 overflow-hidden rounded-lg border">
|
|
37
|
+
<%= poetry_table do %>
|
|
38
|
+
<%= poetry_table_caption(class: "sr-only") { t("accounts.users") } %>
|
|
39
|
+
<%= poetry_table_header do %>
|
|
40
|
+
<%= poetry_table_row do %>
|
|
41
|
+
<%= poetry_table_head { AccountUser.human_attribute_name(:user) } %>
|
|
42
|
+
<%= poetry_table_head(class: "hidden md:table-cell") { AccountUser.human_attribute_name(:email) } %>
|
|
43
|
+
<%= poetry_table_head { AccountUser.human_attribute_name(:roles) } %>
|
|
44
|
+
<%= poetry_table_head(class: "text-right") { tag.span(t(".actions", default: "Actions"), class: "sr-only") } %>
|
|
45
|
+
<% end %>
|
|
46
|
+
<% end %>
|
|
47
|
+
|
|
48
|
+
<%= poetry_table_body do %>
|
|
49
|
+
<% @account_users.each do |account_user| %>
|
|
50
|
+
<% user = account_user.user %>
|
|
51
|
+
<% user_name = user.name || user.email %>
|
|
52
|
+
<%= poetry_table_row do %>
|
|
53
|
+
<%= poetry_table_cell(class: "font-medium") do %>
|
|
54
|
+
<div class="flex items-center gap-3">
|
|
55
|
+
<%= poetry_avatar(src: avatar_url_for(user), label: user_name, size: :sm) { initials.(user_name) } %>
|
|
56
|
+
<div class="min-w-0">
|
|
57
|
+
<div class="truncate"><%= user_name %><%= " (#{t(".you")})" if Current.user == user %></div>
|
|
58
|
+
<div class="truncate text-xs font-normal text-muted-foreground md:hidden"><%= user.email %></div>
|
|
59
|
+
</div>
|
|
60
|
+
<%= poetry_badge(variant: :outline) { t(".2fa") } if user.otp_required_for_login? %>
|
|
61
|
+
</div>
|
|
62
|
+
<% end %>
|
|
63
|
+
<%= poetry_table_cell(class: "hidden text-muted-foreground md:table-cell") { user.email } %>
|
|
64
|
+
<%= poetry_table_cell(class: "text-muted-foreground") { account_user_roles(@account, account_user).join(", ") } %>
|
|
65
|
+
<%= poetry_table_cell(class: "text-right") do %>
|
|
66
|
+
<%= poetry_button(href: edit_account_account_user_path(@account, account_user), variant: :outline, size: :sm) { t(".edit") } if @admin %>
|
|
67
|
+
<% end %>
|
|
68
|
+
<% end %>
|
|
69
|
+
<% end %>
|
|
70
|
+
|
|
71
|
+
<%# Pending invitations %>
|
|
72
|
+
<% @account.account_invitations.each do |account_invitation| %>
|
|
73
|
+
<%= poetry_table_row do %>
|
|
74
|
+
<%= poetry_table_cell(class: "font-medium") do %>
|
|
75
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
76
|
+
<%= poetry_avatar(src: avatar_url_for(account_invitation), label: account_invitation.name, size: :sm) { initials.(account_invitation.name) } %>
|
|
77
|
+
<div class="min-w-0">
|
|
78
|
+
<div class="truncate"><%= account_invitation.name %></div>
|
|
79
|
+
<div class="truncate text-xs font-normal text-muted-foreground md:hidden"><%= account_invitation.email %></div>
|
|
80
|
+
</div>
|
|
81
|
+
<%= poetry_badge(variant: :outline) { t(".awaiting_response") } %>
|
|
82
|
+
</div>
|
|
83
|
+
<% end %>
|
|
84
|
+
<%= poetry_table_cell(class: "hidden text-muted-foreground md:table-cell") { account_invitation.email } %>
|
|
85
|
+
<%= poetry_table_cell(class: "text-muted-foreground") { account_user_roles(@account, account_invitation).join(", ") } %>
|
|
86
|
+
<%= poetry_table_cell(class: "text-right") do %>
|
|
87
|
+
<% if @admin %>
|
|
88
|
+
<div class="flex flex-wrap justify-end gap-2">
|
|
89
|
+
<%= form_with(url: resend_account_account_invitation_path(@account, account_invitation), method: :post) do %>
|
|
90
|
+
<%= poetry_button(type: :submit, variant: :outline, size: :sm) { t(".resend_invite") } %>
|
|
91
|
+
<% end %>
|
|
92
|
+
<%= poetry_button(variant: :outline, size: :sm, data: { controller: "clipboard", clipboard_text: account_invitation_url(account_invitation) }) { t(".copy_link") } %>
|
|
93
|
+
<%= poetry_button(href: edit_account_account_invitation_path(@account, account_invitation), variant: :outline, size: :sm) { t(".edit") } %>
|
|
94
|
+
</div>
|
|
95
|
+
<% end %>
|
|
96
|
+
<% end %>
|
|
97
|
+
<% end %>
|
|
98
|
+
<% end %>
|
|
99
|
+
<% end %>
|
|
100
|
+
<% end %>
|
|
101
|
+
</div>
|
|
102
|
+
<% end %>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's accounts/transfers/_form: pick the new
|
|
2
|
+
owner, then confirm in an AlertDialog whose action submits the PATCH
|
|
3
|
+
form through submit: (Jumpstart put data-turbo-confirm on the form
|
|
4
|
+
instead). The pick is validated server-side (accounts.transfers.update.invalid). %>
|
|
5
|
+
<% candidates = account.users.where.not(users: { id: current_user.id }) %>
|
|
6
|
+
|
|
7
|
+
<section class="space-y-4" aria-labelledby="transfer-ownership-title">
|
|
8
|
+
<div class="space-y-1">
|
|
9
|
+
<h2 id="transfer-ownership-title" class="text-base font-semibold"><%= t(".title") %></h2>
|
|
10
|
+
<p class="text-sm text-muted-foreground"><%= t(".description") %></p>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<%= form_with(url: account_transfer_path(account), method: :patch, id: "account-transfer-form", class: "max-w-md") do %>
|
|
14
|
+
<%= poetry_field_group do %>
|
|
15
|
+
<%= poetry_field(id: "account_transfer_user_id", label_text: t(".new_owner", default: "New owner")) do |field| %>
|
|
16
|
+
<%= poetry_native_select(name: "user_id", class: "w-full",
|
|
17
|
+
options: [[t("helpers.select.prompt", default: "Please select"), ""]] + candidates.map { |user| [user.name || user.email, user.id] },
|
|
18
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
22
|
+
|
|
23
|
+
<%= poetry_alert_dialog do |dialog| %>
|
|
24
|
+
<% dialog.with_trigger(variant: :outline) { t(".transfer") } %>
|
|
25
|
+
<% dialog.with_title { t(".title") } %>
|
|
26
|
+
<% dialog.with_description { t(".are_you_sure") } %>
|
|
27
|
+
<% dialog.with_cancel { t("cancel") } %>
|
|
28
|
+
<% dialog.with_action(variant: :destructive, submit: "account-transfer-form") { t(".transfer") } %>
|
|
29
|
+
<% end %>
|
|
30
|
+
</section>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's application/_account_navbar: the settings
|
|
2
|
+
navigation for the sidebar layout. The class locals of the original are
|
|
3
|
+
accepted for callers that still pass them and ignored; the current entry is
|
|
4
|
+
the aria-current link. %>
|
|
5
|
+
<%# locals: (default_class: nil, active_class: nil, inactive_class: nil) -%>
|
|
6
|
+
<%
|
|
7
|
+
link_class = ->(active) {
|
|
8
|
+
class_names("block rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
|
|
9
|
+
active ? "bg-accent text-accent-foreground" : "text-muted-foreground")
|
|
10
|
+
}
|
|
11
|
+
active_for = ->(path, starts_with = nil) { starts_with ? request.path.start_with?(starts_with) : request.path == path }
|
|
12
|
+
entry = ->(label, path, starts_with = nil) {
|
|
13
|
+
active = active_for.(path, starts_with)
|
|
14
|
+
poetry_link(href: path, current: active, underline: :none, class: link_class.(active)) { label }
|
|
15
|
+
}
|
|
16
|
+
%>
|
|
17
|
+
<nav class="flex flex-col gap-6" aria-label="<%= t(".settings", default: "Settings") %>">
|
|
18
|
+
<div class="flex flex-col gap-1">
|
|
19
|
+
<h2 class="px-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground">User</h2>
|
|
20
|
+
<%= entry.(t(".profile"), edit_registration_path) %>
|
|
21
|
+
<%= entry.(t(".password"), edit_account_password_path) %>
|
|
22
|
+
<% if Jumpstart::Omniauth.enabled_providers.any? %>
|
|
23
|
+
<%= entry.(t(".connected_accounts"), user_connected_accounts_path) %>
|
|
24
|
+
<% end %>
|
|
25
|
+
<%= entry.(t(".accounts"), accounts_path) if Jumpstart.config.team_accounts? %>
|
|
26
|
+
<%= entry.(t(".api_tokens"), api_tokens_path, "/api_tokens") %>
|
|
27
|
+
<% if defined? Refer %>
|
|
28
|
+
<%= entry.(t(".referrals"), referrals_path, "/referrals") %>
|
|
29
|
+
<% end %>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<% billing = Jumpstart.config.payments_enabled? && !hotwire_native_app? && Current.account_billing? %>
|
|
33
|
+
<% if billing || Current.account.team? %>
|
|
34
|
+
<div class="flex flex-col gap-1">
|
|
35
|
+
<h2 class="px-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground">Account</h2>
|
|
36
|
+
<%= entry.(t(".billing"), billing_path, "/billing") if billing %>
|
|
37
|
+
<%= entry.(t(".members"), account_path(Current.account), account_path(Current.account)) if Current.account.team? %>
|
|
38
|
+
</div>
|
|
39
|
+
<% end %>
|
|
40
|
+
</nav>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's announcements/_announcement: one card per
|
|
2
|
+
announcement. The title links to its page, the publish time sits in the
|
|
3
|
+
description, the kind reads as a soft status badge (one treatment family
|
|
4
|
+
across the list: success / info / warning, outline for the neutral
|
|
5
|
+
"update"), and the rich-text body is typeset. %>
|
|
6
|
+
<% kind_variants = { "new" => :success, "improvement" => :info, "fix" => :warning, "update" => :outline } %>
|
|
7
|
+
|
|
8
|
+
<article id="<%= dom_id(announcement) %>">
|
|
9
|
+
<%= poetry_card(title_tag: :h2) do |card| %>
|
|
10
|
+
<% card.with_title do %>
|
|
11
|
+
<%= poetry_link(href: announcement_path(announcement), underline: :hover) { announcement.title } %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% card.with_description do %>
|
|
14
|
+
<% if announcement.published_at? %>
|
|
15
|
+
<span class="capitalize"><%= local_relative_time(announcement.published_at, "weekday-or-date") %></span>
|
|
16
|
+
<% else %>
|
|
17
|
+
<%= t(".draft", default: "Draft") %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% card.with_action do %>
|
|
21
|
+
<%= poetry_badge(variant: kind_variants.fetch(announcement.kind, :outline)) { announcement.kind.humanize.titleize } %>
|
|
22
|
+
<% end %>
|
|
23
|
+
|
|
24
|
+
<%= poetry_typeset do %>
|
|
25
|
+
<%= announcement.description %>
|
|
26
|
+
<% end %>
|
|
27
|
+
<% end %>
|
|
28
|
+
</article>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's announcements/index: a page header with
|
|
2
|
+
the RSS action, one card per announcement (see _announcement), an empty
|
|
3
|
+
state with a next step, and Poetry pagination over Jumpstart's page. %>
|
|
4
|
+
<% content_for :title, t(".title") %>
|
|
5
|
+
|
|
6
|
+
<% content_for :head do %>
|
|
7
|
+
<%= auto_discovery_link_tag :rss, announcements_url(format: :rss), title: t(".title") %>
|
|
8
|
+
<% end %>
|
|
9
|
+
|
|
10
|
+
<% announcements = @announcements.to_a %>
|
|
11
|
+
|
|
12
|
+
<div class="mx-auto w-full max-w-3xl px-4 py-10 lg:px-6">
|
|
13
|
+
<header class="flex flex-col gap-4">
|
|
14
|
+
<div class="flex flex-wrap items-end justify-between gap-4">
|
|
15
|
+
<div class="space-y-1">
|
|
16
|
+
<h1 class="text-3xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
17
|
+
<p class="text-sm text-muted-foreground"><%= t(".description", name: Jumpstart.config.application_name) %></p>
|
|
18
|
+
</div>
|
|
19
|
+
<%= poetry_button(variant: :outline, size: :sm, href: announcements_path(format: :rss)) do |button| %>
|
|
20
|
+
<% button.with_leading { poetry_icon(name: :rss) } %>
|
|
21
|
+
<%= t(".rss", default: "RSS feed") %>
|
|
22
|
+
<% end %>
|
|
23
|
+
</div>
|
|
24
|
+
<%= poetry_separator %>
|
|
25
|
+
</header>
|
|
26
|
+
|
|
27
|
+
<% if announcements.any? %>
|
|
28
|
+
<div class="mt-8 flex flex-col gap-6">
|
|
29
|
+
<%= render announcements %>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<% if @page.multiple_pages? %>
|
|
33
|
+
<div class="mt-8 flex justify-center">
|
|
34
|
+
<%= poetry_pagination_nav(@page) %>
|
|
35
|
+
</div>
|
|
36
|
+
<% end %>
|
|
37
|
+
<% else %>
|
|
38
|
+
<div class="mt-8">
|
|
39
|
+
<%= poetry_empty(media_variant: :icon) do |empty| %>
|
|
40
|
+
<% empty.with_media { poetry_icon(name: :megaphone) } %>
|
|
41
|
+
<% empty.with_title { t(".empty_placeholder") } %>
|
|
42
|
+
<% empty.with_description { t(".empty_description", default: "Nothing has been announced yet. Subscribe to the feed to hear about it first.") } %>
|
|
43
|
+
<%= poetry_button(variant: :outline, href: announcements_path(format: :rss)) do |button| %>
|
|
44
|
+
<% button.with_leading { poetry_icon(name: :rss) } %>
|
|
45
|
+
<%= t(".rss", default: "RSS feed") %>
|
|
46
|
+
<% end %>
|
|
47
|
+
<% end %>
|
|
48
|
+
</div>
|
|
49
|
+
<% end %>
|
|
50
|
+
</div>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/announcements/announcements/show.html.erb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's announcements/show: a back link to the
|
|
2
|
+
list, the kind badge and publish time as the meta row, the title, and the
|
|
3
|
+
rich-text body typeset for reading. The badge mapping mirrors
|
|
4
|
+
_announcement so the two surfaces read as one set. %>
|
|
5
|
+
<% kind_variants = { "new" => :success, "improvement" => :info, "fix" => :warning, "update" => :outline } %>
|
|
6
|
+
|
|
7
|
+
<div class="mx-auto w-full max-w-3xl px-4 py-10 lg:px-6">
|
|
8
|
+
<%= poetry_link(href: announcements_path, underline: :hover, class: "inline-flex items-center gap-1 text-sm font-medium text-muted-foreground") do %>
|
|
9
|
+
<%= poetry_icon(name: :"arrow-left", class: "size-4") %> <%= t(".back") %>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
12
|
+
<article id="<%= dom_id(@announcement) %>" class="mt-6">
|
|
13
|
+
<header class="flex flex-col gap-4">
|
|
14
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
15
|
+
<%= poetry_badge(variant: kind_variants.fetch(@announcement.kind, :outline)) { @announcement.kind.humanize.titleize } %>
|
|
16
|
+
<%= poetry_link(href: announcement_path(@announcement), underline: :hover, class: "text-sm font-medium capitalize text-muted-foreground") do %>
|
|
17
|
+
<% if @announcement.published_at? %>
|
|
18
|
+
<%= local_relative_time(@announcement.published_at, "weekday-or-date") %>
|
|
19
|
+
<% else %>
|
|
20
|
+
<%= t(".draft", default: "Draft") %>
|
|
21
|
+
<% end %>
|
|
22
|
+
<% end %>
|
|
23
|
+
</div>
|
|
24
|
+
<h1 class="text-3xl font-semibold tracking-tight"><%= @announcement.title %></h1>
|
|
25
|
+
<%= poetry_separator %>
|
|
26
|
+
</header>
|
|
27
|
+
|
|
28
|
+
<%= poetry_typeset(class: "mt-6") do %>
|
|
29
|
+
<%= @announcement.description %>
|
|
30
|
+
<% end %>
|
|
31
|
+
</article>
|
|
32
|
+
</div>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/_form.html.erb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's api_tokens/_form. The scopes keep the
|
|
2
|
+
engine's serialization exactly (api_token[scopes][] checkboxes grouped by
|
|
3
|
+
resource behind one clearing hidden field): the builder's checkbox_group
|
|
4
|
+
would flatten the resources under a single "Scopes" label, so each
|
|
5
|
+
scope is a horizontal Field around a bare poetry_checkbox. %>
|
|
6
|
+
<%= form_with(model: api_token, builder: Poetry::Ui::FormBuilder, class: "max-w-md space-y-6") do |form| %>
|
|
7
|
+
<%= render "application/error_messages", resource: form.object %>
|
|
8
|
+
|
|
9
|
+
<%= form.group do %>
|
|
10
|
+
<%= form.input :name, placeholder: t("helpers.placeholder.api_token.name"), autofocus: true %>
|
|
11
|
+
|
|
12
|
+
<% if ApiToken.available_scopes.any? %>
|
|
13
|
+
<% chosen = Array(form.object.scopes).map(&:to_s) %>
|
|
14
|
+
<%= form.fieldset(legend: ApiToken.human_attribute_name(:scopes)) do %>
|
|
15
|
+
<%= hidden_field_tag "api_token[scopes][]", "", id: nil %>
|
|
16
|
+
<%= poetry_field_group do %>
|
|
17
|
+
<% ApiToken.actions_by_resource.each do |resource, actions| %>
|
|
18
|
+
<%= poetry_fieldset(legend: t("api_tokens.resources.#{resource}", default: resource.humanize), legend_variant: :label) do %>
|
|
19
|
+
<%= poetry_field_group(variant: :choices) do %>
|
|
20
|
+
<% actions.each do |action| %>
|
|
21
|
+
<% scope = "#{resource}:#{action}" %>
|
|
22
|
+
<% scope_id = "api_token_scopes_#{resource}_#{action}".parameterize(separator: "_") %>
|
|
23
|
+
<%= poetry_field(id: scope_id, label_text: t("api_tokens.actions.#{action}", default: action.humanize), orientation: :horizontal) do |field| %>
|
|
24
|
+
<%= poetry_checkbox(id: scope_id, name: "api_token[scopes][]", value: scope, checked: chosen.include?(scope), unchecked_value: nil, **field.control_attributes.except("id").transform_keys(&:to_sym)) %>
|
|
25
|
+
<% end %>
|
|
26
|
+
<% end %>
|
|
27
|
+
<% end %>
|
|
28
|
+
<% end %>
|
|
29
|
+
<% end %>
|
|
30
|
+
<% end %>
|
|
31
|
+
<% end %>
|
|
32
|
+
<% end %>
|
|
33
|
+
<% end %>
|
|
34
|
+
|
|
35
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
36
|
+
<%= form.submit %>
|
|
37
|
+
<%= poetry_button(href: (form.object.persisted? ? api_token_path(form.object) : api_tokens_path), variant: :ghost) { t("cancel") } %>
|
|
38
|
+
</div>
|
|
39
|
+
<% end %>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/edit.html.erb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's api_tokens/edit. %>
|
|
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("api_tokens.index.title"), href: api_tokens_path) %>
|
|
7
|
+
<% crumb.with_item(@api_token.name, href: api_token_path(@api_token)) %>
|
|
8
|
+
<% crumb.with_item(t(".title")) %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
11
|
+
<%= poetry_separator %>
|
|
12
|
+
</header>
|
|
13
|
+
|
|
14
|
+
<div class="mt-6">
|
|
15
|
+
<%= render "api_tokens/form", api_token: @api_token %>
|
|
16
|
+
</div>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/index.html.erb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's api_tokens/index: the user's tokens as
|
|
2
|
+
a table, or an Empty state carrying the create action. %>
|
|
3
|
+
<% content_for :title, t(".title") %>
|
|
4
|
+
|
|
5
|
+
<header class="flex flex-wrap items-end justify-between gap-4">
|
|
6
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
7
|
+
<% if @api_tokens.any? %>
|
|
8
|
+
<%= poetry_button(href: new_api_token_path) do |button| %>
|
|
9
|
+
<% button.with_leading { poetry_icon(name: :plus) } %>
|
|
10
|
+
<%= t(".create") %>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% end %>
|
|
13
|
+
</header>
|
|
14
|
+
|
|
15
|
+
<% if @api_tokens.any? %>
|
|
16
|
+
<div class="mt-6 overflow-hidden rounded-lg border">
|
|
17
|
+
<%= poetry_table do %>
|
|
18
|
+
<%= poetry_table_caption(class: "sr-only") { t(".title") } %>
|
|
19
|
+
<%= poetry_table_header do %>
|
|
20
|
+
<%= poetry_table_row do %>
|
|
21
|
+
<%= poetry_table_head { ApiToken.human_attribute_name(:name) } %>
|
|
22
|
+
<%= poetry_table_head { ApiToken.human_attribute_name(:last_used_at) } %>
|
|
23
|
+
<%= poetry_table_head(class: "hidden sm:table-cell") { ApiToken.human_attribute_name(:created_at) } %>
|
|
24
|
+
<%= poetry_table_head(class: "text-right") { tag.span(t(".actions", default: "Actions"), class: "sr-only") } %>
|
|
25
|
+
<% end %>
|
|
26
|
+
<% end %>
|
|
27
|
+
<%= poetry_table_body do %>
|
|
28
|
+
<% @api_tokens.each do |api_token| %>
|
|
29
|
+
<%= poetry_table_row do %>
|
|
30
|
+
<%= poetry_table_cell(class: "font-medium") { poetry_link(href: api_token_path(api_token), underline: :hover) { api_token.name } } %>
|
|
31
|
+
<%= poetry_table_cell(class: "text-muted-foreground") { api_token.last_used_at? ? local_time_ago(api_token.last_used_at) : "—" } %>
|
|
32
|
+
<%= poetry_table_cell(class: "hidden text-muted-foreground sm:table-cell") { api_token.created_at.strftime("%b %e, %Y") } %>
|
|
33
|
+
<%= poetry_table_cell(class: "text-right") { poetry_button(href: api_token_path(api_token), variant: :outline, size: :sm) { t(".view") } } %>
|
|
34
|
+
<% end %>
|
|
35
|
+
<% end %>
|
|
36
|
+
<% end %>
|
|
37
|
+
<% end %>
|
|
38
|
+
</div>
|
|
39
|
+
<% else %>
|
|
40
|
+
<%= poetry_empty(media_variant: :icon, title_tag: :h2, class: "mt-6 rounded-lg border border-dashed py-12") do |empty| %>
|
|
41
|
+
<% empty.with_media { poetry_icon(name: :"key-round") } %>
|
|
42
|
+
<% empty.with_title { t(".none") } %>
|
|
43
|
+
<%= poetry_button(href: new_api_token_path) do |button| %>
|
|
44
|
+
<% button.with_leading { poetry_icon(name: :plus) } %>
|
|
45
|
+
<%= t(".create") %>
|
|
46
|
+
<% end %>
|
|
47
|
+
<% end %>
|
|
48
|
+
<% end %>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's api_tokens/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("api_tokens.index.title"), href: api_tokens_path) %>
|
|
7
|
+
<% crumb.with_item(t(".title")) %>
|
|
8
|
+
<% end %>
|
|
9
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= t(".title") %></h1>
|
|
10
|
+
<%= poetry_separator %>
|
|
11
|
+
</header>
|
|
12
|
+
|
|
13
|
+
<div class="mt-6">
|
|
14
|
+
<%= render "api_tokens/form", api_token: @api_token %>
|
|
15
|
+
</div>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/api_tokens/api_tokens/show.html.erb
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's api_tokens/show. The secret rides a
|
|
2
|
+
SensitiveInput (masked, reveal on demand, copy without revealing - the
|
|
3
|
+
Poetry analogue of blur_secret), the facts a MetadataList, revocation an
|
|
4
|
+
AlertDialog submitting the DELETE form, and the usage snippets are
|
|
5
|
+
CodeBlocks kept behind a Collapsible so the raw token stays off-screen
|
|
6
|
+
until asked for (the intent of the engine's blurred snippet). %>
|
|
7
|
+
<% content_for :title, @api_token.name %>
|
|
8
|
+
|
|
9
|
+
<header class="flex flex-col gap-4">
|
|
10
|
+
<%= poetry_breadcrumb do |crumb| %>
|
|
11
|
+
<% crumb.with_item(t("api_tokens.index.title"), href: api_tokens_path) %>
|
|
12
|
+
<% crumb.with_item(@api_token.name) %>
|
|
13
|
+
<% end %>
|
|
14
|
+
<div class="flex flex-wrap items-center justify-between gap-4">
|
|
15
|
+
<h1 class="text-2xl font-semibold tracking-tight"><%= @api_token.name %></h1>
|
|
16
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
17
|
+
<%= poetry_button(href: edit_api_token_path(@api_token), variant: :outline) { t(".edit") } %>
|
|
18
|
+
<%= form_with(url: api_token_path(@api_token), method: :delete, id: "revoke-token-form", class: "hidden") {} %>
|
|
19
|
+
<%= poetry_alert_dialog do |dialog| %>
|
|
20
|
+
<% dialog.with_trigger(variant: :destructive) { t(".revoke") } %>
|
|
21
|
+
<% dialog.with_title { t(".revoke") } %>
|
|
22
|
+
<% dialog.with_description { t(".confirm") } %>
|
|
23
|
+
<% dialog.with_cancel { t("cancel") } %>
|
|
24
|
+
<% dialog.with_action(variant: :destructive, submit: "revoke-token-form") { t(".revoke") } %>
|
|
25
|
+
<% end %>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<%= poetry_separator %>
|
|
29
|
+
</header>
|
|
30
|
+
|
|
31
|
+
<div class="mt-6 space-y-8">
|
|
32
|
+
<div class="max-w-md space-y-2">
|
|
33
|
+
<%= poetry_label(for_id: "api_token_token") { ApiToken.human_attribute_name(:token) } %>
|
|
34
|
+
<%= poetry_sensitive_input(id: "api_token_token", name: "token", value: @api_token.token, readonly: true, copy: true, label: ApiToken.human_attribute_name(:token)) %>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<%= poetry_metadata_list(columns: :two) do |list| %>
|
|
38
|
+
<% list.with_item(label: ApiToken.human_attribute_name(:created_at)) { @api_token.created_at.strftime("%b %e, %Y") } %>
|
|
39
|
+
<% list.with_item(label: ApiToken.human_attribute_name(:last_used_at)) { @api_token.last_used_at? ? local_time_ago(@api_token.last_used_at) : "—" } %>
|
|
40
|
+
<% if ApiToken.available_scopes.any? %>
|
|
41
|
+
<% ApiToken.actions_by_resource.each do |resource, actions| %>
|
|
42
|
+
<% granted = actions.select { @api_token.can?("#{resource}:#{it}") } %>
|
|
43
|
+
<% list.with_item(label: t("api_tokens.resources.#{resource}", default: resource.humanize)) do %>
|
|
44
|
+
<%= tag.span(granted.map { |action| t("api_tokens.actions.#{action}", default: action.humanize) }.to_sentence.presence || t("api_tokens.no_access"), class: ("text-muted-foreground" if granted.empty?)) %>
|
|
45
|
+
<% end %>
|
|
46
|
+
<% end %>
|
|
47
|
+
<% end %>
|
|
48
|
+
<% end %>
|
|
49
|
+
|
|
50
|
+
<%= poetry_separator %>
|
|
51
|
+
|
|
52
|
+
<section class="space-y-4" aria-labelledby="api-token-usage-title">
|
|
53
|
+
<h2 id="api-token-usage-title" class="text-base font-semibold"><%= t(".auth_header") %></h2>
|
|
54
|
+
<%= poetry_collapsible do |collapsible| %>
|
|
55
|
+
<% collapsible.with_trigger(compose: true) do |wiring| %>
|
|
56
|
+
<%= poetry_button(variant: :outline, size: :sm, **wiring) do |button| %>
|
|
57
|
+
<% button.with_leading { poetry_icon(name: :"code") } %>
|
|
58
|
+
<%= t(".show_examples", default: "Show examples") %>
|
|
59
|
+
<% end %>
|
|
60
|
+
<% end %>
|
|
61
|
+
<div class="mt-4 flex flex-col gap-4">
|
|
62
|
+
<%= poetry_code_block(language: "http", label: t(".http_example", default: "HTTP request"),
|
|
63
|
+
code: "GET /api/v1/me.json\nAccept: application/json\nAuthorization: Bearer #{@api_token.token}") %>
|
|
64
|
+
<%= poetry_code_block(language: "bash", label: t(".curl_example", default: "curl"),
|
|
65
|
+
code: %(curl #{api_v1_me_url(format: :json)} \\\n -H "Accept: application/json" \\\n -H "Authorization: Bearer #{@api_token.token}")) %>
|
|
66
|
+
</div>
|
|
67
|
+
<% end %>
|
|
68
|
+
</section>
|
|
69
|
+
</div>
|
data/lib/generators/poetry_jumpstart_pro/install/templates/auth/application/_error_messages.html.erb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%# Poetry recreation of Jumpstart's application/_error_messages: a form's
|
|
2
|
+
validation errors as a destructive alert (the variant carries role=alert),
|
|
3
|
+
cleared from Turbo's cache like the original. %>
|
|
4
|
+
<%# locals: (resource:) -%>
|
|
5
|
+
<% if resource.errors.any? %>
|
|
6
|
+
<%= poetry_alert(variant: :destructive, class: "mb-6", data: { turbo_temporary: true }) do |errors| %>
|
|
7
|
+
<% errors.with_icon(name: :"circle-alert") %>
|
|
8
|
+
<% errors.with_title do %>
|
|
9
|
+
<%= I18n.t("errors.messages.not_saved", count: resource.errors.count, resource: resource.class.model_name.human.downcase) %>
|
|
10
|
+
<% end %>
|
|
11
|
+
<ul class="list-inside list-disc">
|
|
12
|
+
<% resource.errors.full_messages.each do |message| %>
|
|
13
|
+
<li><%= message %></li>
|
|
14
|
+
<% end %>
|
|
15
|
+
</ul>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% end %>
|