Make various UI improvements (#5890)
- Fix invite modal z-index issues - Improve invite modal design - Add hover state to stats bars on dashboard - Improve feature gate design - Improve trial upgrade CTA design
This commit is contained in:
parent
a2ba1256d2
commit
dec382ccd5
|
|
@ -26,7 +26,7 @@ export default function Bar({
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full relative" style={style}>
|
<div className="w-full h-full relative" style={style}>
|
||||||
<div
|
<div
|
||||||
className={`absolute top-0 left-0 h-full ${bg || ''}`}
|
className={`absolute top-0 left-0 h-full rounded-sm transition-colors duration-150 ${bg || ''}`}
|
||||||
style={{ width: `${width}%` }}
|
style={{ width: `${width}%` }}
|
||||||
></div>
|
></div>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ export default function Conversions({ afterFetchData, onGoalFilterClick }) {
|
||||||
path: conversionsRoute.path,
|
path: conversionsRoute.path,
|
||||||
search: (search) => search
|
search: (search) => search
|
||||||
}}
|
}}
|
||||||
color="bg-red-50"
|
color="bg-red-50 group-hover:bg-red-100"
|
||||||
colMinWidth={90}
|
colMinWidth={90}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ export default function Properties({ afterFetchData }) {
|
||||||
search: (search) => search
|
search: (search) => search
|
||||||
}}
|
}}
|
||||||
maybeHideDetails={true}
|
maybeHideDetails={true}
|
||||||
color="bg-red-50"
|
color="bg-red-50 group-hover:bg-red-100"
|
||||||
colMinWidth={90}
|
colMinWidth={90}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ function EntryPages({ afterFetchData }) {
|
||||||
search: (search) => search
|
search: (search) => search
|
||||||
}}
|
}}
|
||||||
getExternalLinkUrl={getExternalLinkUrl}
|
getExternalLinkUrl={getExternalLinkUrl}
|
||||||
color="bg-orange-50"
|
color="bg-orange-50 group-hover:bg-orange-100"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +99,7 @@ function ExitPages({ afterFetchData }) {
|
||||||
search: (search) => search
|
search: (search) => search
|
||||||
}}
|
}}
|
||||||
getExternalLinkUrl={getExternalLinkUrl}
|
getExternalLinkUrl={getExternalLinkUrl}
|
||||||
color="bg-orange-50"
|
color="bg-orange-50 group-hover:bg-orange-100"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +141,7 @@ function TopPages({ afterFetchData }) {
|
||||||
search: (search) => search
|
search: (search) => search
|
||||||
}}
|
}}
|
||||||
getExternalLinkUrl={getExternalLinkUrl}
|
getExternalLinkUrl={getExternalLinkUrl}
|
||||||
color="bg-orange-50"
|
color="bg-orange-50 group-hover:bg-orange-100"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ export default function ListReport<
|
||||||
return (
|
return (
|
||||||
<div key={listItem.name} style={{ minHeight: ROW_HEIGHT }}>
|
<div key={listItem.name} style={{ minHeight: ROW_HEIGHT }}>
|
||||||
<div
|
<div
|
||||||
className="flex w-full items-center"
|
className="group flex w-full items-center hover:bg-gray-100/60 dark:hover:bg-gray-850 rounded-sm transition-colors duration-150"
|
||||||
style={{ marginTop: ROW_GAP_HEIGHT }}
|
style={{ marginTop: ROW_GAP_HEIGHT }}
|
||||||
>
|
>
|
||||||
{renderBarFor(listItem)}
|
{renderBarFor(listItem)}
|
||||||
|
|
@ -258,7 +258,7 @@ export default function ListReport<
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderBarFor(listItem: TListItem) {
|
function renderBarFor(listItem: TListItem) {
|
||||||
const lightBackground = color || 'bg-green-50'
|
const lightBackground = color || 'bg-green-50 group-hover:bg-green-100'
|
||||||
const metricToPlot = metrics.find((metric) => metric.meta.plot)?.key
|
const metricToPlot = metrics.find((metric) => metric.meta.plot)?.key
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -267,7 +267,7 @@ export default function ListReport<
|
||||||
maxWidthDeduction={undefined}
|
maxWidthDeduction={undefined}
|
||||||
count={listItem[metricToPlot]}
|
count={listItem[metricToPlot]}
|
||||||
all={state.list}
|
all={state.list}
|
||||||
bg={`${lightBackground} dark:bg-gray-500/15`}
|
bg={`${lightBackground} dark:bg-gray-500/15 dark:group-hover:bg-gray-500/30`}
|
||||||
plot={metricToPlot}
|
plot={metricToPlot}
|
||||||
>
|
>
|
||||||
<div className="flex justify-start px-2 py-1.5 group text-sm dark:text-gray-300 relative z-9 break-all w-full">
|
<div className="flex justify-start px-2 py-1.5 group text-sm dark:text-gray-300 relative z-9 break-all w-full">
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ function AllSources({ afterFetchData }) {
|
||||||
metrics={chooseMetrics()}
|
metrics={chooseMetrics()}
|
||||||
detailsLinkProps={{ path: sourcesRoute.path, search: (search) => search }}
|
detailsLinkProps={{ path: sourcesRoute.path, search: (search) => search }}
|
||||||
renderIcon={renderIcon}
|
renderIcon={renderIcon}
|
||||||
color="bg-blue-50"
|
color="bg-blue-50 group-hover:bg-blue-100"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ function Channels({ onClick, afterFetchData }) {
|
||||||
path: channelsRoute.path,
|
path: channelsRoute.path,
|
||||||
search: (search) => search
|
search: (search) => search
|
||||||
}}
|
}}
|
||||||
color="bg-blue-50"
|
color="bg-blue-50 group-hover:bg-blue-100"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ function UTMSources({ tab, afterFetchData }) {
|
||||||
keyLabel={utmTag.label}
|
keyLabel={utmTag.label}
|
||||||
metrics={chooseMetrics()}
|
metrics={chooseMetrics()}
|
||||||
detailsLinkProps={{ path: route?.path, search: (search) => search }}
|
detailsLinkProps={{ path: route?.path, search: (search) => search }}
|
||||||
color="bg-blue-50"
|
color="bg-blue-50 group-hover:bg-blue-100"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,24 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
<div
|
<div
|
||||||
:if={@locked?}
|
:if={@locked?}
|
||||||
id="feature-gate-overlay"
|
id="feature-gate-overlay"
|
||||||
class="absolute backdrop-blur-[6px] bg-white/50 dark:bg-gray-800/50 inset-0 flex justify-center items-center rounded-md"
|
class="absolute backdrop-blur-[8px] bg-white/70 dark:bg-gray-800/50 inset-0 flex justify-center items-center"
|
||||||
>
|
>
|
||||||
<div class="px-6 flex flex-col items-center text-gray-500 dark:text-gray-400">
|
<div class="px-6 flex flex-col items-center gap-y-3">
|
||||||
<Heroicons.lock_closed solid class="size-8 mb-2" />
|
<div class="flex-shrink-0 bg-white dark:bg-gray-700 max-w-max rounded-md p-2 border border-gray-200 dark:border-gray-600 text-indigo-500">
|
||||||
|
<Heroicons.lock_closed solid class="size-6 -mt-px pb-px" />
|
||||||
<span id="lock-notice" class="text-center max-w-sm sm:max-w-md">
|
</div>
|
||||||
To gain access to this feature,
|
<div class="flex flex-col gap-y-1.5 items-center">
|
||||||
<.upgrade_call_to_action current_role={@current_role} current_team={@current_team} />.
|
<h3 class="font-medium text-gray-900 dark:text-gray-100">
|
||||||
</span>
|
Upgrade to unlock
|
||||||
|
</h3>
|
||||||
|
<span
|
||||||
|
id="lock-notice"
|
||||||
|
class="max-w-sm sm:max-w-md mb-2 text-sm text-gray-600 dark:text-gray-100/60 leading-normal text-center"
|
||||||
|
>
|
||||||
|
To access this feature,
|
||||||
|
<.upgrade_call_to_action current_role={@current_role} current_team={@current_team} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -359,23 +368,25 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
not is_nil(assigns.current_role) and assigns.current_role not in [:owner, :billing] ->
|
not is_nil(assigns.current_role) and assigns.current_role not in [:owner, :billing] ->
|
||||||
~H"please reach out to the team owner to upgrade their subscription"
|
~H"ask your team owner to upgrade their subscription."
|
||||||
|
|
||||||
upgrade_assistance_required? ->
|
upgrade_assistance_required? ->
|
||||||
~H"""
|
~H"""
|
||||||
please contact <a href="mailto:hello@plausible.io" class="underline">hello@plausible.io</a>
|
contact
|
||||||
to upgrade your subscription
|
<.styled_link href="mailto:hello@plausible.io" class="font-medium">
|
||||||
|
hello@plausible.io
|
||||||
|
</.styled_link>
|
||||||
|
to upgrade your subscription.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
~H"""
|
~H"""
|
||||||
please
|
<.styled_link
|
||||||
<.link
|
class="inline-block font-medium"
|
||||||
class="underline inline-block"
|
|
||||||
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
|
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
|
||||||
>
|
>
|
||||||
upgrade your subscription
|
upgrade your subscription.
|
||||||
</.link>
|
</.styled_link>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
"bg-indigo-600 text-white hover:bg-indigo-700 focus-visible:outline-indigo-600 disabled:bg-indigo-400/60 disabled:dark:bg-indigo-600/30 disabled:dark:text-white/35",
|
"bg-indigo-600 text-white hover:bg-indigo-700 focus-visible:outline-indigo-600 disabled:bg-indigo-400/60 disabled:dark:bg-indigo-600/30 disabled:dark:text-white/35",
|
||||||
"secondary" =>
|
"secondary" =>
|
||||||
"border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-700 text-gray-800 dark:text-gray-100 hover:text-gray-900 hover:shadow-sm dark:hover:bg-gray-600 dark:hover:text-white disabled:text-gray-700/40 disabled:hover:shadow-none dark:disabled:text-gray-500 dark:disabled:bg-gray-800 dark:disabled:border-gray-800",
|
"border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-700 text-gray-800 dark:text-gray-100 hover:text-gray-900 hover:shadow-sm dark:hover:bg-gray-600 dark:hover:text-white disabled:text-gray-700/40 disabled:hover:shadow-none dark:disabled:text-gray-500 dark:disabled:bg-gray-800 dark:disabled:border-gray-800",
|
||||||
|
"yellow" =>
|
||||||
|
"bg-yellow-600/90 text-white hover:bg-yellow-600 focus-visible:outline-yellow-600 disabled:bg-yellow-400/60 disabled:dark:bg-yellow-600/30 disabled:dark:text-white/35",
|
||||||
"danger" =>
|
"danger" =>
|
||||||
"border border-gray-300 dark:border-gray-800 text-red-600 bg-white dark:bg-gray-800 hover:text-red-700 hover:shadow-sm dark:hover:text-red-400 dark:text-red-500 active:text-red-800 disabled:text-red-700/40 disabled:hover:shadow-none dark:disabled:text-red-500/35 dark:disabled:bg-gray-800"
|
"border border-gray-300 dark:border-gray-800 text-red-600 bg-white dark:bg-gray-800 hover:text-red-700 hover:shadow-sm dark:hover:text-red-400 dark:text-red-500 active:text-red-800 disabled:text-red-700/40 disabled:hover:shadow-none dark:disabled:text-red-500/35 dark:disabled:bg-gray-800"
|
||||||
}
|
}
|
||||||
|
|
@ -95,7 +97,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
|
|
||||||
theme_class =
|
theme_class =
|
||||||
if assigns.disabled do
|
if assigns.disabled do
|
||||||
"bg-gray-400 text-white transition-colors duration-150 dark:text-white dark:text-gray-400 dark:bg-gray-700 cursor-not-allowed"
|
"bg-gray-400 text-white transition-all duration-150 dark:text-white dark:text-gray-400 dark:bg-gray-700 cursor-not-allowed"
|
||||||
else
|
else
|
||||||
@button_themes[assigns.theme]
|
@button_themes[assigns.theme]
|
||||||
end
|
end
|
||||||
|
|
@ -515,7 +517,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
current_role={@current_role}
|
current_role={@current_role}
|
||||||
current_team={@current_team}
|
current_team={@current_team}
|
||||||
>
|
>
|
||||||
<div class="p-6">
|
<div class="p-6 pb-14">
|
||||||
{render_slot(@inner_block)}
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
</PlausibleWeb.Components.Billing.feature_gate>
|
</PlausibleWeb.Components.Billing.feature_gate>
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@ defmodule PlausibleWeb.Live.Components.PrimaModal do
|
||||||
<Modal.modal_overlay
|
<Modal.modal_overlay
|
||||||
transition_enter={{"ease-out duration-300", "opacity-0", "opacity-100"}}
|
transition_enter={{"ease-out duration-300", "opacity-0", "opacity-100"}}
|
||||||
transition_leave={{"ease-in duration-200", "opacity-100", "opacity-0"}}
|
transition_leave={{"ease-in duration-200", "opacity-100", "opacity-0"}}
|
||||||
class="fixed inset-0 bg-gray-500/75 dark:bg-gray-800/75"
|
class="fixed inset-0 z-[9999] bg-gray-500/75 dark:bg-gray-800/75"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="fixed inset-0 w-screen overflow-y-auto">
|
<div class="fixed inset-0 z-[9999] w-screen overflow-y-auto sm:pt-[10vmin]">
|
||||||
<div class="flex min-h-full items-end justify-center p-4 sm:items-center sm:p-0">
|
<div class="flex min-h-full items-end justify-center p-4 sm:items-start sm:p-0">
|
||||||
<Modal.modal_panel
|
<Modal.modal_panel
|
||||||
id={@id <> "-panel"}
|
id={@id <> "-panel"}
|
||||||
class="relative overflow-hidden rounded-lg bg-white dark:bg-gray-900 text-left shadow-xl sm:w-full sm:max-w-lg"
|
class="relative overflow-hidden rounded-lg bg-white dark:bg-gray-900 text-left shadow-xl sm:w-full sm:max-w-lg"
|
||||||
|
|
@ -41,7 +41,7 @@ defmodule PlausibleWeb.Live.Components.PrimaModal do
|
||||||
|
|
||||||
def modal_title(assigns) do
|
def modal_title(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<Modal.modal_title as={&h2/1}>
|
<Modal.modal_title as={&h2/1} class="text-lg font-semibold text-gray-900 dark:text-gray-100">
|
||||||
{render_slot(@inner_block)}
|
{render_slot(@inner_block)}
|
||||||
</Modal.modal_title>
|
</Modal.modal_title>
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -656,38 +656,31 @@ defmodule PlausibleWeb.Live.Sites do
|
||||||
def invitation_modal(assigns) do
|
def invitation_modal(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<PlausibleWeb.Live.Components.PrimaModal.modal id={@id}>
|
<PlausibleWeb.Live.Components.PrimaModal.modal id={@id}>
|
||||||
<div class="bg-white dark:bg-gray-850 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="p-5 pb-3 sm:p-6 sm:pb-3">
|
||||||
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
|
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
|
||||||
<button
|
<button
|
||||||
phx-click={Prima.Modal.close()}
|
phx-click={Prima.Modal.close()}
|
||||||
class="bg-white dark:bg-gray-800 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-indigo-500"
|
class="text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400"
|
||||||
>
|
>
|
||||||
<span class="sr-only">Close</span>
|
<span class="sr-only">Close</span>
|
||||||
<Heroicons.x_mark class="size-6" />
|
<Heroicons.x_mark class="size-6" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="flex flex-col gap-y-4 text-center sm:text-left">
|
||||||
<div class="mx-auto shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10">
|
<PlausibleWeb.Live.Components.PrimaModal.modal_title>
|
||||||
<Heroicons.user_group class="size-6" />
|
You're invited to {@site.domain}
|
||||||
</div>
|
</PlausibleWeb.Live.Components.PrimaModal.modal_title>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div>
|
||||||
<PlausibleWeb.Live.Components.PrimaModal.modal_title>
|
<p class="text-sm text-gray-600 dark:text-gray-400 text-pretty">
|
||||||
Invitation for {@site.domain}
|
You've been added as <b class="capitalize">{@invitation.invitation.role}</b>
|
||||||
</PlausibleWeb.Live.Components.PrimaModal.modal_title>
|
to the {@site.domain} analytics dashboard.
|
||||||
<div class="mt-2">
|
<%= if !(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)) &&
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-200">
|
@invitation.invitation.role == :owner do %>
|
||||||
You've been invited to the {@site.domain} analytics dashboard as <b class="capitalize">{@invitation.invitation.role}</b>.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
:if={
|
|
||||||
!(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)) &&
|
|
||||||
@invitation.invitation.role == :owner
|
|
||||||
}
|
|
||||||
class="mt-2 text-sm text-gray-500 dark:text-gray-200"
|
|
||||||
>
|
|
||||||
If you accept the ownership transfer, you will be responsible for billing going forward.
|
If you accept the ownership transfer, you will be responsible for billing going forward.
|
||||||
</div>
|
<% else %>
|
||||||
</div>
|
Welcome aboard!
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<.notice
|
<.notice
|
||||||
|
|
@ -730,30 +723,30 @@ defmodule PlausibleWeb.Live.Sites do
|
||||||
You are unable to accept the ownership of this site because your account does not have a subscription. To become the owner of this site, you should upgrade to a suitable plan.
|
You are unable to accept the ownership of this site because your account does not have a subscription. To become the owner of this site, you should upgrade to a suitable plan.
|
||||||
</.notice>
|
</.notice>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 dark:bg-gray-850 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
<div class="flex flex-col sm:flex-row-reverse gap-3 p-5 sm:p-6">
|
||||||
<.button
|
<.button
|
||||||
:if={!(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan))}
|
:if={!(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan))}
|
||||||
mt?={false}
|
mt?={false}
|
||||||
class="sm:ml-3 w-full sm:w-auto sm:text-sm"
|
class="w-full sm:w-auto sm:text-sm"
|
||||||
data-method="post"
|
data-method="post"
|
||||||
data-csrf={Plug.CSRFProtection.get_csrf_token()}
|
data-csrf={Plug.CSRFProtection.get_csrf_token()}
|
||||||
data-to={"/sites/invitations/#{@invitation.invitation.invitation_id}/accept"}
|
data-to={"/sites/invitations/#{@invitation.invitation.invitation_id}/accept"}
|
||||||
data-autofocus
|
data-autofocus
|
||||||
>
|
>
|
||||||
Accept & Continue
|
Accept and continue
|
||||||
</.button>
|
</.button>
|
||||||
<.button_link
|
<.button_link
|
||||||
:if={Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)}
|
:if={Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)}
|
||||||
mt?={false}
|
mt?={false}
|
||||||
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
|
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
|
||||||
class="sm:ml-3 w-full sm:w-auto sm:text-sm"
|
class="w-full sm:w-auto sm:text-sm"
|
||||||
data-autofocus
|
data-autofocus
|
||||||
>
|
>
|
||||||
Upgrade
|
Upgrade
|
||||||
</.button_link>
|
</.button_link>
|
||||||
<.button_link
|
<.button_link
|
||||||
mt?={false}
|
mt?={false}
|
||||||
class="w-full sm:w-auto mr-2 sm:text-sm mt-2 sm:mt-0"
|
class="w-full sm:w-auto sm:text-sm"
|
||||||
href="#"
|
href="#"
|
||||||
theme="secondary"
|
theme="secondary"
|
||||||
data-method="post"
|
data-method="post"
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,19 @@
|
||||||
:if={ee?() and Plausible.Teams.on_trial?(@conn.assigns[:current_team])}
|
:if={ee?() and Plausible.Teams.on_trial?(@conn.assigns[:current_team])}
|
||||||
class="hidden sm:block"
|
class="hidden sm:block"
|
||||||
>
|
>
|
||||||
<.styled_link
|
<div class="flex items-center p-1 rounded-lg bg-yellow-100 dark:bg-yellow-600/35 overflow-hidden">
|
||||||
class="flex items-center h-[40px] px-3 py-2 text-sm text-yellow-700 hover:text-yellow-800 dark:text-yellow-500 dark:hover:text-yellow-500 font-medium rounded-md bg-yellow-100 dark:bg-yellow-800/40 dark:hover:bg-yellow-800/50 transition-colors duration-150"
|
<span class="px-3 text-sm font-medium text-gray-900 dark:text-gray-100">
|
||||||
href={Routes.settings_path(@conn, :subscription)}
|
{trial_notification(@conn.assigns[:current_team])}
|
||||||
>
|
</span>
|
||||||
{trial_notification(@conn.assigns[:current_team])}
|
<.button_link
|
||||||
</.styled_link>
|
href={Routes.settings_path(@conn, :subscription)}
|
||||||
|
theme="yellow"
|
||||||
|
mt?={false}
|
||||||
|
class="!px-3 !py-2"
|
||||||
|
>
|
||||||
|
Upgrade
|
||||||
|
</.button_link>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="w-full sm:w-auto">
|
<li class="w-full sm:w-auto">
|
||||||
<.dropdown>
|
<.dropdown>
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,9 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
assert class_of_element(html, "#feature-gate-inner-block-container") =~
|
assert element_exists?(html, "#feature-gate-inner-block-container")
|
||||||
"pointer-events-none"
|
assert element_exists?(html, "#feature-gate-overlay")
|
||||||
|
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
|
||||||
assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "renders a blur overlay for a teamless account" do
|
test "renders a blur overlay for a teamless account" do
|
||||||
|
|
@ -32,10 +31,9 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
assert class_of_element(html, "#feature-gate-inner-block-container") =~
|
assert element_exists?(html, "#feature-gate-inner-block-container")
|
||||||
"pointer-events-none"
|
assert element_exists?(html, "#feature-gate-overlay")
|
||||||
|
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
|
||||||
assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not render a blur overlay if feature access is granted", %{user: user} do
|
test "does not render a blur overlay if feature access is granted", %{user: user} do
|
||||||
|
|
@ -47,9 +45,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
refute class_of_element(html, "#feature-gate-inner-block-container") =~
|
assert element_exists?(html, "#feature-gate-inner-block-container")
|
||||||
"pointer-events-none"
|
|
||||||
|
|
||||||
refute element_exists?(html, "#feature-gate-overlay")
|
refute element_exists?(html, "#feature-gate-overlay")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -89,7 +85,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
assert text_of_element(html, "#lock-notice") =~ "reach out to the team owner"
|
assert text_of_element(html, "#lock-notice") =~ "ask your team owner"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
|
||||||
)
|
)
|
||||||
|
|
||||||
assert rendered =~ "This team is limited to 10 users"
|
assert rendered =~ "This team is limited to 10 users"
|
||||||
assert rendered =~ "please reach out to the team owner to upgrade their subscription"
|
assert rendered =~ "ask your team owner to upgrade their subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :ee_only
|
@tag :ee_only
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
||||||
conn = get(conn, "/#{site.domain}/settings/funnels")
|
conn = get(conn, "/#{site.domain}/settings/funnels")
|
||||||
resp = conn |> html_response(200)
|
resp = conn |> html_response(200)
|
||||||
|
|
||||||
assert text(resp) =~ "please upgrade your subscription"
|
assert text(resp) =~ "upgrade your subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "lists funnels for the site and renders help link", %{conn: conn, site: site} do
|
test "lists funnels for the site and renders help link", %{conn: conn, site: site} do
|
||||||
|
|
@ -33,7 +33,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
|
||||||
assert resp =~ "From blog to signup"
|
assert resp =~ "From blog to signup"
|
||||||
assert resp =~ "From signup to blog"
|
assert resp =~ "From signup to blog"
|
||||||
refute resp =~ "Your account does not have access"
|
refute resp =~ "Your account does not have access"
|
||||||
refute resp =~ "please upgrade your subscription"
|
refute resp =~ "upgrade your subscription"
|
||||||
assert element_exists?(resp, "a[href=\"https://plausible.io/docs/funnel-analysis\"]")
|
assert element_exists?(resp, "a[href=\"https://plausible.io/docs/funnel-analysis\"]")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
|
||||||
|> html_response(200)
|
|> html_response(200)
|
||||||
|> text_of_element("#lock-notice")
|
|> text_of_element("#lock-notice")
|
||||||
|
|
||||||
assert lock_notice =~ "please upgrade your subscription"
|
assert lock_notice =~ "upgrade your subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :ee_only
|
@tag :ee_only
|
||||||
|
|
@ -38,7 +38,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
|
||||||
|> html_response(200)
|
|> html_response(200)
|
||||||
|> text_of_element("#lock-notice")
|
|> text_of_element("#lock-notice")
|
||||||
|
|
||||||
refute lock_notice =~ "please upgrade your subscription"
|
refute lock_notice =~ "upgrade your subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "lists props for the site and renders links", %{conn: conn, site: site} do
|
test "lists props for the site and renders links", %{conn: conn, site: site} do
|
||||||
|
|
@ -56,7 +56,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
|
||||||
assert resp =~ "amount"
|
assert resp =~ "amount"
|
||||||
assert resp =~ "logged_in"
|
assert resp =~ "logged_in"
|
||||||
assert resp =~ "is_customer"
|
assert resp =~ "is_customer"
|
||||||
refute resp =~ "please upgrade your subscription"
|
refute resp =~ "upgrade your subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "lists props with disallow actions", %{conn: conn, site: site} do
|
test "lists props with disallow actions", %{conn: conn, site: site} do
|
||||||
|
|
@ -133,7 +133,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
|
||||||
assert resp =~ "amount"
|
assert resp =~ "amount"
|
||||||
assert resp =~ "logged_in"
|
assert resp =~ "logged_in"
|
||||||
assert resp =~ "is_customer"
|
assert resp =~ "is_customer"
|
||||||
refute resp =~ "please upgrade your subscription"
|
refute resp =~ "upgrade your subscription"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "if no props are allowed, a proper info is displayed", %{
|
test "if no props are allowed, a proper info is displayed", %{
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,9 @@ defmodule PlausibleWeb.Live.TeamSetupTest do
|
||||||
|
|
||||||
{:ok, _lv, html} = live(conn, @url)
|
{:ok, _lv, html} = live(conn, @url)
|
||||||
|
|
||||||
assert class_of_element(html, "#feature-gate-inner-block-container") =~
|
assert element_exists?(html, "#feature-gate-inner-block-container")
|
||||||
"pointer-events-none"
|
assert element_exists?(html, "#feature-gate-overlay")
|
||||||
|
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
|
||||||
assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur-[6px]"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue