Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/js/dashboard/stats/bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function Bar({
return (
<div className="w-full h-full relative" style={style}>
<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}%` }}
></div>
{children}
Expand Down
2 changes: 1 addition & 1 deletion assets/js/dashboard/stats/behaviours/conversions.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function Conversions({ afterFetchData, onGoalFilterClick }) {
path: conversionsRoute.path,
search: (search) => search
}}
color="bg-red-50"
color="bg-red-50 group-hover:bg-red-100"
colMinWidth={90}
/>
)
Expand Down
2 changes: 1 addition & 1 deletion assets/js/dashboard/stats/behaviours/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export default function Properties({ afterFetchData }) {
search: (search) => search
}}
maybeHideDetails={true}
color="bg-red-50"
color="bg-red-50 group-hover:bg-red-100"
colMinWidth={90}
/>
)
Expand Down
6 changes: 3 additions & 3 deletions assets/js/dashboard/stats/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function EntryPages({ afterFetchData }) {
search: (search) => search
}}
getExternalLinkUrl={getExternalLinkUrl}
color="bg-orange-50"
color="bg-orange-50 group-hover:bg-orange-100"
/>
)
}
Expand Down Expand Up @@ -99,7 +99,7 @@ function ExitPages({ afterFetchData }) {
search: (search) => search
}}
getExternalLinkUrl={getExternalLinkUrl}
color="bg-orange-50"
color="bg-orange-50 group-hover:bg-orange-100"
/>
)
}
Expand Down Expand Up @@ -141,7 +141,7 @@ function TopPages({ afterFetchData }) {
search: (search) => search
}}
getExternalLinkUrl={getExternalLinkUrl}
color="bg-orange-50"
color="bg-orange-50 group-hover:bg-orange-100"
/>
)
}
Expand Down
6 changes: 3 additions & 3 deletions assets/js/dashboard/stats/reports/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ export default function ListReport<
return (
<div key={listItem.name} style={{ minHeight: ROW_HEIGHT }}>
<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 }}
>
{renderBarFor(listItem)}
Expand All @@ -258,7 +258,7 @@ export default function ListReport<
}

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

return (
Expand All @@ -267,7 +267,7 @@ export default function ListReport<
maxWidthDeduction={undefined}
count={listItem[metricToPlot]}
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}
>
<div className="flex justify-start px-2 py-1.5 group text-sm dark:text-gray-300 relative z-9 break-all w-full">
Expand Down
6 changes: 3 additions & 3 deletions assets/js/dashboard/stats/sources/source-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function AllSources({ afterFetchData }) {
metrics={chooseMetrics()}
detailsLinkProps={{ path: sourcesRoute.path, search: (search) => search }}
renderIcon={renderIcon}
color="bg-blue-50"
color="bg-blue-50 group-hover:bg-blue-100"
/>
)
}
Expand Down Expand Up @@ -122,7 +122,7 @@ function Channels({ onClick, afterFetchData }) {
path: channelsRoute.path,
search: (search) => search
}}
color="bg-blue-50"
color="bg-blue-50 group-hover:bg-blue-100"
/>
)
}
Expand Down Expand Up @@ -166,7 +166,7 @@ function UTMSources({ tab, afterFetchData }) {
keyLabel={utmTag.label}
metrics={chooseMetrics()}
detailsLinkProps={{ path: route?.path, search: (search) => search }}
color="bg-blue-50"
color="bg-blue-50 group-hover:bg-blue-100"
/>
)
}
Expand Down
43 changes: 27 additions & 16 deletions lib/plausible_web/components/billing/billing.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,24 @@ defmodule PlausibleWeb.Components.Billing do
<div
:if={@locked?}
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">
<Heroicons.lock_closed solid class="size-8 mb-2" />

<span id="lock-notice" class="text-center max-w-sm sm:max-w-md">
To gain access to this feature,
<.upgrade_call_to_action current_role={@current_role} current_team={@current_team} />.
</span>
<div class="px-6 flex flex-col items-center gap-y-3">
<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" />
</div>
<div class="flex flex-col gap-y-1.5 items-center">
<h3 class="font-medium text-gray-900 dark:text-gray-100">
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>
"""
Expand Down Expand Up @@ -359,23 +368,25 @@ defmodule PlausibleWeb.Components.Billing do

cond do
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? ->
~H"""
please contact <a href="mailto:[email protected]" class="underline">[email protected]</a>
to upgrade your subscription
contact
<.styled_link href="mailto:[email protected]" class="font-medium">
[email protected]
</.styled_link>
to upgrade your subscription.
"""

true ->
~H"""
please
<.link
class="underline inline-block"
<.styled_link
class="inline-block font-medium"
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
>
upgrade your subscription
</.link>
upgrade your subscription.
</.styled_link>
"""
end
end
Expand Down
6 changes: 4 additions & 2 deletions lib/plausible_web/components/generic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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",
"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",
"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" =>
"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"
}
Expand Down Expand Up @@ -95,7 +97,7 @@ defmodule PlausibleWeb.Components.Generic do

theme_class =
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
@button_themes[assigns.theme]
end
Expand Down Expand Up @@ -515,7 +517,7 @@ defmodule PlausibleWeb.Components.Generic do
current_role={@current_role}
current_team={@current_team}
>
<div class="p-6">
<div class="p-6 pb-14">
{render_slot(@inner_block)}
</div>
</PlausibleWeb.Components.Billing.feature_gate>
Expand Down
8 changes: 4 additions & 4 deletions lib/plausible_web/live/components/prima_modal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ defmodule PlausibleWeb.Live.Components.PrimaModal do
<Modal.modal_overlay
transition_enter={{"ease-out duration-300", "opacity-0", "opacity-100"}}
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="flex min-h-full items-end justify-center p-4 sm:items-center sm:p-0">
<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-start sm:p-0">
<Modal.modal_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"
Expand All @@ -41,7 +41,7 @@ defmodule PlausibleWeb.Live.Components.PrimaModal do

def modal_title(assigns) do
~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)}
</Modal.modal_title>
"""
Expand Down
49 changes: 21 additions & 28 deletions lib/plausible_web/live/sites.ex
Original file line number Diff line number Diff line change
Expand Up @@ -656,38 +656,31 @@ defmodule PlausibleWeb.Live.Sites do
def invitation_modal(assigns) do
~H"""
<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">
<button
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>
<Heroicons.x_mark class="size-6" />
</button>
</div>
<div class="sm:flex sm:items-start">
<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">
<Heroicons.user_group class="size-6" />
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<PlausibleWeb.Live.Components.PrimaModal.modal_title>
Invitation for {@site.domain}
</PlausibleWeb.Live.Components.PrimaModal.modal_title>
<div class="mt-2">
<p class="text-sm text-gray-500 dark:text-gray-200">
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"
>
<div class="flex flex-col gap-y-4 text-center sm:text-left">
<PlausibleWeb.Live.Components.PrimaModal.modal_title>
You're invited to {@site.domain}
</PlausibleWeb.Live.Components.PrimaModal.modal_title>
<div>
<p class="text-sm text-gray-600 dark:text-gray-400 text-pretty">
You've been added as <b class="capitalize">{@invitation.invitation.role}</b>
to the {@site.domain} analytics dashboard.
<%= if !(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)) &&
@invitation.invitation.role == :owner do %>
If you accept the ownership transfer, you will be responsible for billing going forward.
</div>
</div>
<% else %>
Welcome aboard!
<% end %>
</p>
</div>
</div>
<.notice
Expand Down Expand Up @@ -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.
</.notice>
</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
:if={!(Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan))}
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-csrf={Plug.CSRFProtection.get_csrf_token()}
data-to={"/sites/invitations/#{@invitation.invitation.invitation_id}/accept"}
data-autofocus
>
Accept &amp; Continue
Accept and continue
</.button>
<.button_link
:if={Map.get(@invitation, :exceeded_limits) || Map.get(@invitation, :no_plan)}
mt?={false}
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
>
Upgrade
</.button_link>
<.button_link
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="#"
theme="secondary"
data-method="post"
Expand Down
19 changes: 13 additions & 6 deletions lib/plausible_web/templates/layout/_header.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,19 @@
:if={ee?() and Plausible.Teams.on_trial?(@conn.assigns[:current_team])}
class="hidden sm:block"
>
<.styled_link
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"
href={Routes.settings_path(@conn, :subscription)}
>
{trial_notification(@conn.assigns[:current_team])}
</.styled_link>
<div class="flex items-center p-1 rounded-lg bg-yellow-100 dark:bg-yellow-600/35 overflow-hidden">
<span class="px-3 text-sm font-medium text-gray-900 dark:text-gray-100">
{trial_notification(@conn.assigns[:current_team])}
</span>
<.button_link
href={Routes.settings_path(@conn, :subscription)}
theme="yellow"
mt?={false}
class="!px-3 !py-2"
>
Upgrade
</.button_link>
</div>
</li>
<li class="w-full sm:w-auto">
<.dropdown>
Expand Down
20 changes: 8 additions & 12 deletions test/plausible_web/components/billing/billing_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ defmodule PlausibleWeb.Components.BillingTest do
}
|> render_feature_gate()

assert class_of_element(html, "#feature-gate-inner-block-container") =~
"pointer-events-none"

assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur"
assert element_exists?(html, "#feature-gate-inner-block-container")
assert element_exists?(html, "#feature-gate-overlay")
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
end

test "renders a blur overlay for a teamless account" do
Expand All @@ -32,10 +31,9 @@ defmodule PlausibleWeb.Components.BillingTest do
}
|> render_feature_gate()

assert class_of_element(html, "#feature-gate-inner-block-container") =~
"pointer-events-none"

assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur"
assert element_exists?(html, "#feature-gate-inner-block-container")
assert element_exists?(html, "#feature-gate-overlay")
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
end

test "does not render a blur overlay if feature access is granted", %{user: user} do
Expand All @@ -47,9 +45,7 @@ defmodule PlausibleWeb.Components.BillingTest do
}
|> render_feature_gate()

refute class_of_element(html, "#feature-gate-inner-block-container") =~
"pointer-events-none"

assert element_exists?(html, "#feature-gate-inner-block-container")
refute element_exists?(html, "#feature-gate-overlay")
end

Expand Down Expand Up @@ -89,7 +85,7 @@ defmodule PlausibleWeb.Components.BillingTest do
}
|> 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

Expand Down
2 changes: 1 addition & 1 deletion test/plausible_web/components/billing/notice_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
)

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

@tag :ee_only
Expand Down
Loading