mirror of
https://github.com/plausible/analytics.git
synced 2024-12-28 12:01:39 +03:00
22ecbe7bc7
* move format_price to Plausible.Billing * move PlausibleWeb.Components.Billing file to subfolder * extract new Notice module * rename test file and module name * move growth_grandfathered notice to notice.ex * extract a PlanBenefits module * extract PlanBox component * extract PageviewSlider component * fix plan benefits text color
499 lines
21 KiB
Plaintext
499 lines
21 KiB
Plaintext
<div x-data="{disable2FAOpen: false, regenerate2FAOpen: false}">
|
|
<%= if full_build?() do %>
|
|
<div class="max-w-2xl px-8 pt-4 pb-8 mx-auto mt-24 bg-white border-t-2 border-orange-200 rounded rounded-t-none shadow-md dark:bg-gray-800 dark:border-orange-200 ">
|
|
<div class="flex flex-wrap justify-between">
|
|
<h2 class="text-xl font-black dark:text-gray-100 w-max mr-4 mt-2">Subscription Plan</h2>
|
|
<div class="gap-x-2 mt-2 inline-flex">
|
|
<span
|
|
:if={@subscription && Plausible.Billing.Plans.business_tier?(@subscription)}
|
|
class={[
|
|
"w-max px-2.5 py-0.5 rounded-md text-sm font-bold leading-5 text-indigo-600 bg-blue-100 dark:text-yellow-200 dark:border dark:bg-inherit dark:border-yellow-200"
|
|
]}
|
|
>
|
|
Business
|
|
</span>
|
|
<span
|
|
:if={@subscription}
|
|
class={[
|
|
"w-max px-2.5 py-0.5 rounded-md text-sm font-bold leading-5",
|
|
subscription_colors(@subscription.status)
|
|
]}
|
|
>
|
|
<%= present_subscription_status(@subscription.status) %>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="my-4 border-b border-gray-400"></div>
|
|
|
|
<PlausibleWeb.Components.Billing.Notice.subscription_cancelled
|
|
user={@user}
|
|
dismissable={false}
|
|
/>
|
|
|
|
<div class="flex flex-col items-center justify-between mt-8 sm:flex-row sm:items-start">
|
|
<PlausibleWeb.Components.Billing.monthly_quota_box
|
|
user={@user}
|
|
subscription={@subscription}
|
|
/>
|
|
<div
|
|
class="h-32 px-2 py-4 my-4 text-center bg-gray-100 rounded dark:bg-gray-900"
|
|
style="width: 11.75rem;"
|
|
>
|
|
<h4 class="font-black dark:text-gray-100">Next bill amount</h4>
|
|
<%= if Plausible.Billing.Subscription.Status.in?(@subscription, [Plausible.Billing.Subscription.Status.active(), Plausible.Billing.Subscription.Status.past_due()]) do %>
|
|
<div class="py-2 text-xl font-medium dark:text-gray-100">
|
|
<%= PlausibleWeb.BillingView.present_currency(@subscription.currency_code) %><%= @subscription.next_bill_amount %>
|
|
</div>
|
|
<.styled_link :if={@subscription.update_url} href={@subscription.update_url}>
|
|
Update billing info
|
|
</.styled_link>
|
|
<% else %>
|
|
<div class="py-2 text-xl font-medium dark:text-gray-100">---</div>
|
|
<% end %>
|
|
</div>
|
|
<div
|
|
class="h-32 px-2 py-4 my-4 text-center bg-gray-100 rounded dark:bg-gray-900"
|
|
style="width: 11.75rem;"
|
|
>
|
|
<h4 class="font-black dark:text-gray-100">Next bill date</h4>
|
|
|
|
<%= if @subscription && @subscription.next_bill_date && Plausible.Billing.Subscription.Status.in?(@subscription, [Plausible.Billing.Subscription.Status.active(), Plausible.Billing.Subscription.Status.past_due()]) do %>
|
|
<div class="py-2 text-xl font-medium dark:text-gray-100">
|
|
<%= Timex.format!(@subscription.next_bill_date, "{Mshort} {D}, {YYYY}") %>
|
|
</div>
|
|
<span class="text-gray-600 dark:text-gray-400">
|
|
(<%= subscription_interval(@subscription) %> billing)
|
|
</span>
|
|
<% else %>
|
|
<div class="py-2 text-xl font-medium dark:text-gray-100">---</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
|
|
<PlausibleWeb.Components.Billing.render_monthly_pageview_usage
|
|
usage={@pageview_usage}
|
|
limit={@pageview_limit}
|
|
/>
|
|
|
|
<article class="mt-8">
|
|
<h1 class="text-xl mb-3 font-bold dark:text-gray-100">Sites & team members usage</h1>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_table>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_row
|
|
id="site-usage-row"
|
|
title="Owned sites"
|
|
usage={@site_usage}
|
|
limit={@site_limit}
|
|
/>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_row
|
|
id="team-member-usage-row"
|
|
title="Team members"
|
|
usage={@team_member_usage}
|
|
limit={@team_member_limit}
|
|
/>
|
|
</PlausibleWeb.Components.Billing.usage_and_limits_table>
|
|
</article>
|
|
|
|
<%= cond do %>
|
|
<% Plausible.Billing.Subscriptions.resumable?(@subscription) && @subscription.cancel_url -> %>
|
|
<div class="mt-8">
|
|
<%= link("Cancel my subscription",
|
|
to: @subscription.cancel_url,
|
|
class:
|
|
"inline-block mt-4 px-4 py-2 border border-gray-300 dark:border-gray-500 text-sm leading-5 font-medium rounded-md text-red-700 bg-white dark:bg-gray-800 hover:text-red-500 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150"
|
|
) %>
|
|
</div>
|
|
<% true -> %>
|
|
<div class="mt-8">
|
|
<PlausibleWeb.Components.Billing.upgrade_link user={@user} />
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
|
|
<%= case @invoices do %>
|
|
<% {:error, :no_invoices} -> %>
|
|
<% {:error, :request_failed} -> %>
|
|
<div class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 bg-white border-t-2 border-orange-200 rounded rounded-t-none shadow-md dark:bg-gray-800">
|
|
<h2 class="text-xl font-black dark:text-gray-100">Invoices</h2>
|
|
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
|
<p class="text-center text-black dark:text-gray-100 m-2">
|
|
Something went wrong
|
|
</p>
|
|
</div>
|
|
<% {:ok, invoice_list} when is_list(invoice_list) -> %>
|
|
<div class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 bg-white border-t-2 border-orange-200 rounded rounded-t-none shadow-md dark:bg-gray-800">
|
|
<h2 class="text-xl font-black dark:text-gray-100">Invoices</h2>
|
|
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead>
|
|
<tr>
|
|
<th
|
|
scope="col"
|
|
class="py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
|
>
|
|
Date
|
|
</th>
|
|
<th
|
|
scope="col"
|
|
class="py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
|
>
|
|
Amount
|
|
</th>
|
|
<th
|
|
scope="col"
|
|
class="py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider"
|
|
>
|
|
Invoice
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<%= for invoice <- format_invoices(invoice_list) do %>
|
|
<tbody class="divide-y divide-gray-200">
|
|
<tr>
|
|
<td class="py-4 text-sm text-gray-800 dark:text-gray-200 font-medium">
|
|
<%= invoice.date %>
|
|
</td>
|
|
<td class="py-4 text-sm text-gray-800 dark:text-gray-200">
|
|
<%= invoice.currency <> invoice.amount %>
|
|
</td>
|
|
<td class="py-4 text-sm text-indigo-500">
|
|
<%= link("Link", to: invoice.url, target: "_blank") %>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
<% end %>
|
|
</table>
|
|
</div>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<div class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 bg-white border-t-2 border-green-500 rounded rounded-t-none shadow-md dark:bg-gray-800">
|
|
<h2 class="text-xl font-black dark:text-gray-100">Dashboard Appearance</h2>
|
|
|
|
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
|
|
|
<%= form_for @settings_changeset, "/settings", [class: "max-w-sm"], fn f -> %>
|
|
<div class="col-span-4 sm:col-span-2">
|
|
<%= label(f, :theme, "Theme Selection",
|
|
class: "block text-sm font-medium leading-5 text-gray-700 dark:text-gray-300"
|
|
) %>
|
|
<%= select(f, :theme, Plausible.Themes.options(),
|
|
class:
|
|
"dark:bg-gray-900 mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-500 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:text-gray-100 cursor-pointer"
|
|
) %>
|
|
</div>
|
|
|
|
<PlausibleWeb.Components.Generic.button type="submit" class="mt-4">
|
|
Save
|
|
</PlausibleWeb.Components.Generic.button>
|
|
<% end %>
|
|
</div>
|
|
|
|
<div class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 bg-white border-t-2 border-green-500 rounded rounded-t-none shadow-md dark:bg-gray-800">
|
|
<h2 id="setup-2fa" class="text-xl font-black dark:text-gray-100">
|
|
Two-Factor Authentication (2FA)
|
|
</h2>
|
|
|
|
<p class="text-sm mt-2 text-gray-600 dark:text-gray-400">
|
|
Two-Factor Authentication protects your account by adding an extra security step when you log in.
|
|
</p>
|
|
|
|
<%= if @totp_enabled? do %>
|
|
<button
|
|
x-on:click="disable2FAOpen = true; $refs.disable2FAPassword.value = ''"
|
|
type="button"
|
|
class="inline-block mt-4 px-4 py-2 border border-gray-300 dark:border-gray-500 text-sm leading-5 font-medium rounded-md text-red-700 bg-white dark:bg-gray-800 hover:text-red-500 dark:hover:text-red-400 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150"
|
|
>
|
|
Disable 2FA
|
|
</button>
|
|
|
|
<p class="mt-2 text-gray-600 text-sm dark:text-gray-400">
|
|
Lost your recovery codes?
|
|
<a
|
|
href="#setup-2fa"
|
|
x-on:click="regenerate2FAOpen = true; $refs.regenerate2FAPassword.value = ''"
|
|
class="underline text-indigo-600"
|
|
>
|
|
Generate new
|
|
</a>
|
|
</p>
|
|
<% else %>
|
|
<%= form_for @conn.params, Routes.auth_path(@conn, :initiate_2fa_setup), fn _ -> %>
|
|
<PlausibleWeb.Components.Generic.button type="submit" class="mt-4">
|
|
Enable 2FA
|
|
</PlausibleWeb.Components.Generic.button>
|
|
<% end %>
|
|
<% end %>
|
|
</div>
|
|
|
|
<div class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 bg-white border-t-2 border-indigo-100 rounded rounded-t-none shadow-md dark:bg-gray-800 dark:border-indigo-500">
|
|
<h2 id="change-account-name" class="text-xl font-black dark:text-gray-100">
|
|
Change account name
|
|
</h2>
|
|
|
|
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
|
|
|
<%= form_for @settings_changeset, "/settings#change-account-name", [class: "max-w-sm"], fn f -> %>
|
|
<div class="my-4">
|
|
<%= label(f, :name, class: "block text-sm font-medium text-gray-700 dark:text-gray-300") %>
|
|
<div class="mt-1">
|
|
<%= text_input(f, :name,
|
|
class:
|
|
"shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800"
|
|
) %>
|
|
<%= error_tag(f, :name) %>
|
|
</div>
|
|
</div>
|
|
<PlausibleWeb.Components.Generic.button type="submit" class="mt-4">
|
|
Save
|
|
</PlausibleWeb.Components.Generic.button>
|
|
<% end %>
|
|
</div>
|
|
|
|
<div class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 bg-white border-t-2 border-red-600 rounded rounded-t-none shadow-md dark:bg-gray-800">
|
|
<h2 id="change-email-address" class="text-xl font-black dark:text-gray-100">
|
|
Change email address
|
|
</h2>
|
|
|
|
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
|
|
|
<%= form_for @email_changeset, "/settings/email#change-email-address", [class: "max-w-sm"], fn f -> %>
|
|
<div class="my-4">
|
|
<%= label(f, :password, "Account password",
|
|
class: "block text-sm font-medium text-gray-700 dark:text-gray-300"
|
|
) %>
|
|
<div class="mt-1">
|
|
<%= password_input(f, :password,
|
|
class:
|
|
"shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800"
|
|
) %>
|
|
<%= error_tag(f, :password) %>
|
|
</div>
|
|
</div>
|
|
<div class="my-4">
|
|
<%= label(f, :current_email, "Current email",
|
|
class: "block text-sm font-medium text-gray-700 dark:text-gray-300"
|
|
) %>
|
|
<div class="mt-1">
|
|
<%= email_input(f, :current_email,
|
|
readonly: true,
|
|
value: f.data.email,
|
|
class:
|
|
"shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800 bg-gray-100"
|
|
) %>
|
|
</div>
|
|
</div>
|
|
<div class="my-4">
|
|
<%= label(f, :email, "New email",
|
|
class: "block text-sm font-medium text-gray-700 dark:text-gray-300"
|
|
) %>
|
|
<div class="mt-1">
|
|
<%= email_input(f, :email,
|
|
value: f.params["email"],
|
|
class:
|
|
"shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-500 rounded-md"
|
|
) %>
|
|
<%= error_tag(f, :email) %>
|
|
</div>
|
|
</div>
|
|
|
|
<%= submit("Change my email",
|
|
class:
|
|
"inline-block mt-4 px-4 py-2 border border-gray-300 dark:border-gray-500 text-sm leading-5 font-medium rounded-md text-red-700 bg-white dark:bg-gray-800 hover:text-red-500 dark:hover:text-red-400 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150"
|
|
) %>
|
|
<% end %>
|
|
</div>
|
|
|
|
<div
|
|
id="api-keys"
|
|
class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 bg-white border-t-2 border-indigo-100 rounded rounded-t-none shadow-md dark:bg-gray-800 dark:border-indigo-500"
|
|
>
|
|
<h2 class="text-xl font-black dark:text-gray-100">API Keys</h2>
|
|
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
|
|
|
<PlausibleWeb.Components.Billing.Notice.premium_feature
|
|
billable_user={@current_user}
|
|
current_user={@current_user}
|
|
feature_mod={Plausible.Billing.Feature.StatsAPI}
|
|
/>
|
|
|
|
<div class="flex flex-col mt-6">
|
|
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
|
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
|
<%= if Enum.any?(@user.api_keys) do %>
|
|
<div class="overflow-hidden border-b border-gray-200 shadow dark:border-gray-900 sm:rounded-lg">
|
|
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-900">
|
|
<thead class="bg-gray-50 dark:bg-gray-900">
|
|
<tr>
|
|
<th
|
|
scope="col"
|
|
class="px-6 py-3 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-gray-100"
|
|
>
|
|
Name
|
|
</th>
|
|
<th
|
|
scope="col"
|
|
class="px-6 py-3 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-gray-100"
|
|
>
|
|
Key
|
|
</th>
|
|
<th scope="col" class="relative px-6 py-3">
|
|
<span class="sr-only">Revoke</span>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%= for api_key <- @user.api_keys do %>
|
|
<tr class="bg-white dark:bg-gray-800">
|
|
<td class="px-6 py-4 text-sm font-medium text-gray-900 dark:text-gray-100 whitespace-nowrap">
|
|
<%= api_key.name %>
|
|
</td>
|
|
<td class="px-6 py-4 text-sm text-gray-500 dark:text-gray-100 whitespace-nowrap">
|
|
<%= api_key.key_prefix %><%= String.duplicate("*", 32 - 6) %>
|
|
</td>
|
|
<td class="px-6 py-4 text-sm font-medium text-right whitespace-nowrap">
|
|
<%= button("Revoke",
|
|
to: "/settings/api-keys/#{api_key.id}",
|
|
class: "text-red-600 hover:text-red-900",
|
|
method: :delete,
|
|
"data-confirm":
|
|
"Are you sure you want to revoke this key? This action cannot be reversed."
|
|
) %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<% end %>
|
|
|
|
<PlausibleWeb.Components.Generic.button_link
|
|
:if={Plausible.Billing.Feature.StatsAPI.check_availability(@current_user) == :ok}
|
|
href={Routes.auth_path(@conn, :new_api_key)}
|
|
class="mt-4"
|
|
>
|
|
+ New API Key
|
|
</PlausibleWeb.Components.Generic.button_link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="max-w-2xl px-8 pt-6 pb-8 mx-auto mt-16 mb-24 bg-white border-t-2 border-red-600 rounded rounded-t-none shadow-md dark:bg-gray-800">
|
|
<div class="flex items-center justify-between">
|
|
<h2 class="text-xl font-black dark:text-gray-100">Delete account</h2>
|
|
</div>
|
|
|
|
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
|
|
|
<p class="dark:text-gray-100">
|
|
Deleting your account removes all sites and stats you've collected
|
|
</p>
|
|
|
|
<%= if Plausible.Billing.Subscription.Status.active?(@subscription) do %>
|
|
<span class="mt-6 bg-gray-300 button dark:bg-gray-600 hover:shadow-none hover:bg-gray-300 cursor-not-allowed">
|
|
Delete my account
|
|
</span>
|
|
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
|
Your account cannot be deleted because you have an active subscription. If you want to delete your account, please cancel your subscription first.
|
|
</p>
|
|
<% else %>
|
|
<%= link("Delete my account",
|
|
to: "/me",
|
|
class:
|
|
"inline-block mt-4 px-4 py-2 border border-gray-300 dark:border-gray-500 text-sm leading-5 font-medium rounded-md text-red-700 bg-white dark:bg-gray-800 hover:text-red-500 dark:hover:text-red-400 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150",
|
|
method: "delete",
|
|
data: [
|
|
confirm:
|
|
"Deleting your account will also delete all the sites and data that you own. This action cannot be reversed. Are you sure?"
|
|
]
|
|
) %>
|
|
<% end %>
|
|
</div>
|
|
|
|
<PlausibleWeb.Components.TwoFactor.modal
|
|
:let={f}
|
|
id="disable-2fa-modal"
|
|
state_param="disable2FAOpen"
|
|
form_data={@conn.params}
|
|
form_target={Routes.auth_path(@conn, :disable_2fa)}
|
|
title="Disable Two-Factor Authentication?"
|
|
>
|
|
<:icon>
|
|
<Heroicons.shield_exclamation class="h-6 w-6" />
|
|
</:icon>
|
|
<:buttons>
|
|
<.button type="submit" class="w-full sm:w-auto">
|
|
Disable 2FA
|
|
</.button>
|
|
</:buttons>
|
|
|
|
<div class="text-sm mt-2">
|
|
Once disabled, verification codes from the authenticator application and current recovery codes will become invalid. 2FA will have to be setup from the start.
|
|
</div>
|
|
|
|
<div class="text-sm mt-2">
|
|
Enter your password to disable 2FA.
|
|
</div>
|
|
|
|
<div class="mt-3">
|
|
<%= password_input(f, :password,
|
|
id: "disable_2fa_password",
|
|
placeholder: "Enter password",
|
|
"x-ref": "disable2FAPassword",
|
|
class:
|
|
"shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800"
|
|
) %>
|
|
</div>
|
|
</PlausibleWeb.Components.TwoFactor.modal>
|
|
|
|
<PlausibleWeb.Components.TwoFactor.modal
|
|
:let={f}
|
|
id="regenerate-2fa-modal"
|
|
state_param="regenerate2FAOpen"
|
|
form_data={@conn.params}
|
|
form_target={Routes.auth_path(@conn, :generate_2fa_recovery_codes)}
|
|
onsubmit="document.getElementById('generate-2fa-recovery-button').disabled = true"
|
|
title="Generate New Recovery Codes?"
|
|
>
|
|
<:icon>
|
|
<Heroicons.key class="h-6 w-6" />
|
|
</:icon>
|
|
|
|
<:buttons>
|
|
<.button
|
|
id="generate-2fa-recovery-button"
|
|
type="submit"
|
|
class="w-full sm:w-auto [&>span.label-enabled]:block [&>span.label-disabled]:hidden [&[disabled]>span.label-enabled]:hidden [&[disabled]>span.label-disabled]:block"
|
|
>
|
|
<span class="label-enabled pointer-events-none">
|
|
Generate New Codes
|
|
</span>
|
|
|
|
<span class="label-disabled">
|
|
<.spinner class="inline-block h-5 w-5 mr-2 text-white dark:text-gray-400" />
|
|
Generating Codes
|
|
</span>
|
|
</.button>
|
|
</:buttons>
|
|
|
|
<div class="text-sm mt-2">
|
|
If you generate new codes, the old ones will become invalid.
|
|
</div>
|
|
|
|
<div class="text-sm mt-2">
|
|
Enter your password to continue.
|
|
</div>
|
|
|
|
<div class="mt-3 w-full">
|
|
<%= password_input(f, :password,
|
|
id: "regenerate_2fa_password",
|
|
placeholder: "Enter password",
|
|
"x-ref": "regenerate2FAPassword",
|
|
class:
|
|
"w-full shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800"
|
|
) %>
|
|
</div>
|
|
</PlausibleWeb.Components.TwoFactor.modal>
|
|
</div>
|