mirror of
https://github.com/plausible/analytics.git
synced 2024-12-24 01:54:34 +03:00
Display tooltips on plan change when limits exceeded (#4048)
* Reapply "Display upgrade tooltips for exceeded limits (#4032)"
This reverts commit 76e910d45c
.
* Switch to alpinejs controlled tooltips
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* Remove unused selector
* Refactor plan limits warning and extract tooltip component
* Remove redundant check
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
This commit is contained in:
parent
b2009aa158
commit
ad9141a9d0
@ -164,6 +164,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||||||
])
|
])
|
||||||
|
|
||||||
subscription_deleted = Subscription.Status.deleted?(subscription)
|
subscription_deleted = Subscription.Status.deleted?(subscription)
|
||||||
|
usage_check = check_usage_within_plan_limits(assigns)
|
||||||
|
|
||||||
{checkout_disabled, disabled_message} =
|
{checkout_disabled, disabled_message} =
|
||||||
cond do
|
cond do
|
||||||
@ -173,7 +174,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||||||
change_plan_link_text == "Currently on this plan" && not subscription_deleted ->
|
change_plan_link_text == "Currently on this plan" && not subscription_deleted ->
|
||||||
{true, nil}
|
{true, nil}
|
||||||
|
|
||||||
assigns.available && !usage_within_plan_limits?(assigns) ->
|
usage_check != :ok ->
|
||||||
{true, "Your usage exceeds this plan"}
|
{true, "Your usage exceeds this plan"}
|
||||||
|
|
||||||
billing_details_expired ->
|
billing_details_expired ->
|
||||||
@ -183,6 +184,15 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||||||
{false, nil}
|
{false, nil}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
exceeded_plan_limits =
|
||||||
|
case usage_check do
|
||||||
|
{:error, {:over_plan_limits, limits}} ->
|
||||||
|
limits
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
features_to_lose = assigns.usage.features -- assigns.plan_to_render.features
|
features_to_lose = assigns.usage.features -- assigns.plan_to_render.features
|
||||||
|
|
||||||
assigns =
|
assigns =
|
||||||
@ -191,6 +201,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||||||
|> assign(:change_plan_link_text, change_plan_link_text)
|
|> assign(:change_plan_link_text, change_plan_link_text)
|
||||||
|> assign(:checkout_disabled, checkout_disabled)
|
|> assign(:checkout_disabled, checkout_disabled)
|
||||||
|> assign(:disabled_message, disabled_message)
|
|> assign(:disabled_message, disabled_message)
|
||||||
|
|> assign(:exceeded_plan_limits, exceeded_plan_limits)
|
||||||
|> assign(:confirm_message, losing_features_message(features_to_lose))
|
|> assign(:confirm_message, losing_features_message(features_to_lose))
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
@ -201,13 +212,37 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||||||
Upgrade
|
Upgrade
|
||||||
</PlausibleWeb.Components.Billing.paddle_button>
|
</PlausibleWeb.Components.Billing.paddle_button>
|
||||||
<% end %>
|
<% end %>
|
||||||
<p :if={@disabled_message} class="h-0 text-center text-sm text-red-700 dark:text-red-500">
|
<p
|
||||||
|
:if={@disabled_message}
|
||||||
|
class="h-0 text-center text-sm text-red-700 dark:text-red-500 disabled-message"
|
||||||
|
>
|
||||||
|
<%= if @exceeded_plan_limits != [] do %>
|
||||||
|
<PlausibleWeb.Components.Generic.tooltip>
|
||||||
<%= @disabled_message %>
|
<%= @disabled_message %>
|
||||||
|
<:tooltip_content>
|
||||||
|
Your usage exceeds the following limit(s):<br /><br />
|
||||||
|
<p :for={limit <- @exceeded_plan_limits}>
|
||||||
|
<%= Phoenix.Naming.humanize(limit) %><br />
|
||||||
|
</p>
|
||||||
|
</:tooltip_content>
|
||||||
|
</PlausibleWeb.Components.Generic.tooltip>
|
||||||
|
<% else %>
|
||||||
|
<%= @disabled_message %>
|
||||||
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
defp usage_within_plan_limits?(%{usage: usage, user: user, plan_to_render: plan}) do
|
defp check_usage_within_plan_limits(%{available: false}) do
|
||||||
|
{:error, :plan_unavailable}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_usage_within_plan_limits(%{
|
||||||
|
available: true,
|
||||||
|
usage: usage,
|
||||||
|
user: user,
|
||||||
|
plan_to_render: plan
|
||||||
|
}) do
|
||||||
# At this point, the user is *not guaranteed* to have a `trial_expiry_date`,
|
# At this point, the user is *not guaranteed* to have a `trial_expiry_date`,
|
||||||
# because in the past we've let users upgrade without that constraint, as
|
# because in the past we've let users upgrade without that constraint, as
|
||||||
# well as transfer sites to those accounts. to these accounts we won't be
|
# well as transfer sites to those accounts. to these accounts we won't be
|
||||||
@ -232,7 +267,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
Quota.ensure_within_plan_limits(usage, plan, limit_checking_opts) == :ok
|
Quota.ensure_within_plan_limits(usage, plan, limit_checking_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_paddle_product_id(%Plan{monthly_product_id: plan_id}, :monthly), do: plan_id
|
defp get_paddle_product_id(%Plan{monthly_product_id: plan_id}, :monthly), do: plan_id
|
||||||
|
@ -318,6 +318,32 @@ defmodule PlausibleWeb.Components.Generic do
|
|||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
slot :inner_block, required: true
|
||||||
|
slot :tooltip_content, required: true
|
||||||
|
|
||||||
|
def tooltip(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div x-data="{sticky: false, hovered: false}" class="tooltip-wrapper relative">
|
||||||
|
<p
|
||||||
|
x-on:click="sticky = true; hovered = true"
|
||||||
|
x-on:click.outside="sticky = false; hovered = false"
|
||||||
|
x-on:mouseover="hovered = true"
|
||||||
|
x-on:mouseout="hovered = false"
|
||||||
|
class="cursor-pointer text-sm text-red-700 dark:text-red-500 mt-1 flex justify-center align-items-center"
|
||||||
|
>
|
||||||
|
<%= render_slot(@inner_block) %>
|
||||||
|
<Heroicons.information_circle class="w-5 h-5 ml-2" />
|
||||||
|
</p>
|
||||||
|
<span
|
||||||
|
x-show="hovered || sticky"
|
||||||
|
class="bg-gray-900 pointer-events-none absolute bottom-10 margin-x-auto left-10 right-10 transition-opacity p-4 rounded text-white"
|
||||||
|
>
|
||||||
|
<%= render_slot(List.first(@tooltip_content)) %>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
attr :rest, :global, include: ~w(fill stroke stroke-width)
|
attr :rest, :global, include: ~w(fill stroke stroke-width)
|
||||||
attr :name, :atom, required: true
|
attr :name, :atom, required: true
|
||||||
attr :outline, :boolean, default: true
|
attr :outline, :boolean, default: true
|
||||||
|
@ -19,6 +19,7 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
|
|||||||
@slider_value "#slider-value"
|
@slider_value "#slider-value"
|
||||||
|
|
||||||
@growth_plan_box "#growth-plan-box"
|
@growth_plan_box "#growth-plan-box"
|
||||||
|
@growth_plan_tooltip "#growth-plan-box .tooltip-wrapper span"
|
||||||
@growth_price_tag_amount "#growth-price-tag-amount"
|
@growth_price_tag_amount "#growth-price-tag-amount"
|
||||||
@growth_price_tag_interval "#growth-price-tag-interval"
|
@growth_price_tag_interval "#growth-price-tag-interval"
|
||||||
@growth_highlight_pill "#{@growth_plan_box} #highlight-pill"
|
@growth_highlight_pill "#{@growth_plan_box} #highlight-pill"
|
||||||
@ -243,6 +244,7 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
|
|||||||
|
|
||||||
refute class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
refute class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
||||||
refute class_of_element(doc, @business_checkout_button) =~ "pointer-events-none"
|
refute class_of_element(doc, @business_checkout_button) =~ "pointer-events-none"
|
||||||
|
refute element_exists?(doc, @growth_plan_tooltip)
|
||||||
|
|
||||||
generate_usage_for(site, 1)
|
generate_usage_for(site, 1)
|
||||||
|
|
||||||
@ -251,6 +253,9 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
|
|||||||
|
|
||||||
assert class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
assert class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
||||||
assert class_of_element(doc, @business_checkout_button) =~ "pointer-events-none"
|
assert class_of_element(doc, @business_checkout_button) =~ "pointer-events-none"
|
||||||
|
|
||||||
|
assert text_of_element(doc, @growth_plan_tooltip) ==
|
||||||
|
"Your usage exceeds the following limit(s): Monthly pageview limit"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "allows upgrade to a 10k plan with a pageview allowance margin of 0.3 when trial ended 10 days ago",
|
test "allows upgrade to a 10k plan with a pageview allowance margin of 0.3 when trial ended 10 days ago",
|
||||||
@ -497,6 +502,9 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
|
|||||||
|
|
||||||
assert text_of_element(doc, @growth_plan_box) =~ "Your usage exceeds this plan"
|
assert text_of_element(doc, @growth_plan_box) =~ "Your usage exceeds this plan"
|
||||||
assert class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
assert class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
||||||
|
|
||||||
|
assert text_of_element(doc, @growth_plan_tooltip) ==
|
||||||
|
"Your usage exceeds the following limit(s): Team member limit"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "checkout is disabled when sites usage exceeds rendered plan limit", %{
|
test "checkout is disabled when sites usage exceeds rendered plan limit", %{
|
||||||
@ -509,6 +517,31 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
|
|||||||
|
|
||||||
assert text_of_element(doc, @growth_plan_box) =~ "Your usage exceeds this plan"
|
assert text_of_element(doc, @growth_plan_box) =~ "Your usage exceeds this plan"
|
||||||
assert class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
assert class_of_element(doc, @growth_checkout_button) =~ "pointer-events-none"
|
||||||
|
|
||||||
|
assert text_of_element(doc, @growth_plan_tooltip) ==
|
||||||
|
"Your usage exceeds the following limit(s): Site limit"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "when more than one limit is exceeded, the tooltip enumerates them", %{
|
||||||
|
conn: conn,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
for _ <- 1..11, do: insert(:site, members: [user])
|
||||||
|
|
||||||
|
insert(:site,
|
||||||
|
memberships: [
|
||||||
|
build(:site_membership, user: user, role: :owner),
|
||||||
|
build(:site_membership, user: build(:user)),
|
||||||
|
build(:site_membership, user: build(:user)),
|
||||||
|
build(:site_membership, user: build(:user)),
|
||||||
|
build(:site_membership, user: build(:user))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
{:ok, _lv, doc} = get_liveview(conn)
|
||||||
|
|
||||||
|
assert text_of_element(doc, @growth_plan_tooltip) =~ "Team member limit"
|
||||||
|
assert text_of_element(doc, @growth_plan_tooltip) =~ "Site limit"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "checkout is not disabled when pageview usage exceeded but next upgrade allowed by override",
|
test "checkout is not disabled when pageview usage exceeded but next upgrade allowed by override",
|
||||||
|
Loading…
Reference in New Issue
Block a user