mirror of
https://github.com/plausible/analytics.git
synced 2024-12-29 20:42:01 +03:00
a4b9c3b8ba
* Disable super-admin checks on small build * Mute a test writing to stdout * Move sampling outside of small build * Convert waiting_first_pageview to heex and stop relying on env vars * Set site limit unlimited on small build * Stop relying on app env to get trial expiry * Remove custom domains - including migration * Remove is_selfhosted from layout view * Quota fixup * Stop relying on app env for self hosted registration * Stop relying on app env for pass reset success * Apply on_trial? check only on full build * Update templates relying on app env * Adjusts auth controller tests for small build * Trial fixup * Fixup * Stop relying on app env * Rest of the fsckn owl * Update typespecs * Fix dialyzer warning * Remove unused module * Credo + format * GeoIP is not, for full build * Use `small_build?()` where applicable * Implement bypassing FirstLaunchPlug without insertions * Get Marko's patchde58a18a85
* Test is-dbip=false presence * Fix typespec * Remove future hardcodes * Handle `nil` from `Plausible.Geo.database_type()` * Remove XXX marker * Use one typespec for two clauses * Introduce `MIX_ENV=small_dev` * Revert "Use one typespec for two clauses" This reverts commit8d8cd21764
.
395 lines
17 KiB
Plaintext
395 lines
17 KiB
Plaintext
<%= 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.subscription_cancelled_notice
|
|
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}
|
|
business_tier={FunWithFlags.enabled?(:business_tier, for: @user)}
|
|
/>
|
|
<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 @subscription && @subscription.status in [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>
|
|
<%= if @subscription.update_url do %>
|
|
<%= link("Update billing info",
|
|
to: @subscription.update_url,
|
|
class: "text-sm text-indigo-500 font-medium"
|
|
) %>
|
|
<% end %>
|
|
<% 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 && @subscription.status in [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>
|
|
<div class="text-sm font-medium text-gray-600 dark:text-gray-400">
|
|
(<%= subscription_interval(@subscription) %> billing)
|
|
</div>
|
|
<% else %>
|
|
<div class="py-2 text-xl font-medium dark:text-gray-100">---</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
|
|
<article class="mt-8">
|
|
<h1 class="text-xl font-bold dark:text-gray-100">Usage & Limits</h1>
|
|
<h2 class="mt-1 mb-3 text-sm text-gray-500 leading-5 dark:text-gray-200">
|
|
Your usage across all of your sites and the limits of your plan
|
|
</h2>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_table>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_row
|
|
title="Total billable pageviews (last 30 days)"
|
|
usage={@total_pageview_usage}
|
|
limit={@total_pageview_limit}
|
|
/>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_row
|
|
pad
|
|
title="Pageviews"
|
|
usage={@pageview_usage}
|
|
class="font-normal text-gray-500 dark:text-gray-400"
|
|
/>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_row
|
|
pad
|
|
title="Custom events"
|
|
usage={@custom_event_usage}
|
|
class="font-normal text-gray-500 dark:text-gray-400"
|
|
/>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_row
|
|
title="Owned sites"
|
|
usage={@site_usage}
|
|
limit={@site_limit}
|
|
/>
|
|
<PlausibleWeb.Components.Billing.usage_and_limits_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}
|
|
business_tier={FunWithFlags.enabled?(:business_tier, for: @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-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.premium_feature_notice
|
|
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 @subscription && @subscription.status == Plausible.Billing.Subscription.Status.active() 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>
|