Skip to content

Commit b8d64e2

Browse files
sanne-sanaerosol
andauthored
Updated empty states across settings (#5874)
* Updated empty states across settings * Fix funnels and props functionality not hiding when toggled off - Add show_content? attribute to generic tile component - Ensure content is hidden when toggled off - Avoid rendering border and empty space when toggled off - Fix formatting * Update personal sites empty state * Make `tile` component lv-embeddable (#5891) * Use new tile component for funnels, goals, imports and custom properties - Update the settings live views to use the new tile component - Ensure tile component is updated when feature visibility is toggled - Extract `no_search_results` and `empty_state` components for better readability - Extract `highlighted` component - Update tests * Add empty states for team sites and simplify empty state logic - Hide top bar on `/sites` when empty state is shown - Extract empty state logic to a separate function - Show the same empty state for both personal and team sites, with different copy - extract search logic to a separate function - add tests for various empty states cases * Clean up: - remove HTTP feature visibility routes now that we're doing it 100% via LV - add tests for feature toggling - move "site_role" to where it's used (upgrade CTA), since there were already some feature-related function calls there - fix random test failures left * Fixup --------- Co-authored-by: Adam Rutkowski <[email protected]>
1 parent 25d4015 commit b8d64e2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1402
-1064
lines changed

extra/lib/plausible_web/live/funnel_settings.ex

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,40 +50,61 @@ defmodule PlausibleWeb.Live.FunnelSettings do
5050
<div id="funnel-settings-main">
5151
<.flash_messages flash={@flash} />
5252
53-
<%= if @setup_funnel? do %>
54-
{live_render(
55-
@socket,
56-
PlausibleWeb.Live.FunnelSettings.Form,
57-
id: "funnels-form",
58-
session: %{
59-
"domain" => @domain,
60-
"funnel_id" => @funnel_id
61-
}
62-
)}
63-
<% end %>
64-
<div :if={@goal_count >= Funnel.min_steps()}>
65-
<.live_component
66-
module={PlausibleWeb.Live.FunnelSettings.List}
67-
id="funnels-list"
68-
funnels={@displayed_funnels}
69-
filter_text={@filter_text}
70-
/>
71-
</div>
72-
73-
<div :if={@goal_count < Funnel.min_steps()} class="flex flex-col items-center">
74-
<h1 class="mt-4 text-center">
75-
Ready to dig into user flows?
76-
</h1>
77-
<p class="mt-4 mb-6 max-w-lg text-sm text-gray-500 dark:text-gray-400 leading-5 text-center">
78-
Set up a few goals first (e.g. <b>"Signup"</b>, <b>"Visit /"</b>, or <b>"Scroll 50% on /blog/*"</b>) and return here to build your first funnel!
79-
</p>
80-
<.button_link
81-
class="mb-2"
82-
href={PlausibleWeb.Router.Helpers.site_path(@socket, :settings_goals, @domain)}
53+
<.tile
54+
docs="funnel-analysis"
55+
feature_mod={Plausible.Billing.Feature.Funnels}
56+
feature_toggle?={true}
57+
show_content?={!Plausible.Billing.Feature.Funnels.opted_out?(@site)}
58+
site={@site}
59+
current_user={@current_user}
60+
current_team={@current_team}
61+
>
62+
<:title>
63+
Funnels
64+
</:title>
65+
<:subtitle :if={Enum.count(@all_funnels) > 0}>
66+
Compose goals into funnels to track user flows and conversion rates.
67+
</:subtitle>
68+
<%= if @setup_funnel? do %>
69+
{live_render(
70+
@socket,
71+
PlausibleWeb.Live.FunnelSettings.Form,
72+
id: "funnels-form",
73+
session: %{
74+
"domain" => @domain,
75+
"funnel_id" => @funnel_id
76+
}
77+
)}
78+
<% end %>
79+
<div :if={@goal_count >= Funnel.min_steps()}>
80+
<.live_component
81+
module={PlausibleWeb.Live.FunnelSettings.List}
82+
id="funnels-list"
83+
funnels={@displayed_funnels}
84+
filter_text={@filter_text}
85+
/>
86+
</div>
87+
88+
<div
89+
:if={@goal_count < Funnel.min_steps()}
90+
class="flex flex-col items-center justify-center pt-5 pb-6 max-w-md mx-auto"
8391
>
84-
Set up goals →
85-
</.button_link>
86-
</div>
92+
<h3 class="text-center text-base font-medium text-gray-900 dark:text-gray-100 leading-7">
93+
Ready to dig into user flows?
94+
</h3>
95+
<p class="text-center text-sm mt-1 text-gray-500 dark:text-gray-400 leading-5 text-pretty">
96+
Set up a few goals like <.highlighted>Signup</.highlighted>, <.highlighted>Visit /</.highlighted>, or
97+
<.highlighted>Scroll 50% on /blog/*</.highlighted>
98+
first, then return here to build your first funnel.
99+
</p>
100+
<.button_link
101+
class="mt-4"
102+
href={PlausibleWeb.Router.Helpers.site_path(@socket, :settings_goals, @domain)}
103+
>
104+
Set up goals →
105+
</.button_link>
106+
</div>
107+
</.tile>
87108
</div>
88109
"""
89110
end
@@ -147,4 +168,8 @@ defmodule PlausibleWeb.Live.FunnelSettings do
147168
def handle_info(:cancel_setup_funnel, socket) do
148169
{:noreply, assign(socket, setup_funnel?: false, funnel_id: nil)}
149170
end
171+
172+
def handle_info({:feature_toggled, flash_msg, updated_site}, socket) do
173+
{:noreply, assign(put_flash(socket, :success, flash_msg), site: updated_site)}
174+
end
150175
end

extra/lib/plausible_web/live/funnel_settings/list.ex

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ defmodule PlausibleWeb.Live.FunnelSettings.List do
1010
use PlausibleWeb, :live_component
1111

1212
def render(assigns) do
13+
assigns = assign(assigns, :searching?, String.trim(assigns.filter_text) != "")
14+
1315
~H"""
1416
<div>
15-
<.filter_bar filter_text={@filter_text} placeholder="Search Funnels">
16-
<.button id="add-funnel-button" phx-click="add-funnel" mt?={false}>
17-
Add funnel
18-
</.button>
19-
</.filter_bar>
17+
<%= if @searching? or Enum.count(@funnels) > 0 do %>
18+
<.filter_bar filter_text={@filter_text} placeholder="Search Funnels">
19+
<.button id="add-funnel-button" phx-click="add-funnel" mt?={false}>
20+
Add funnel
21+
</.button>
22+
</.filter_bar>
23+
<% end %>
2024
2125
<%= if Enum.count(@funnels) > 0 do %>
2226
<.table rows={@funnels}>
@@ -42,19 +46,44 @@ defmodule PlausibleWeb.Live.FunnelSettings.List do
4246
</:tbody>
4347
</.table>
4448
<% else %>
45-
<p class="mt-12 mb-8 text-sm text-center">
46-
<span :if={String.trim(@filter_text) != ""}>
47-
No funnels found for this site. Please refine or
48-
<.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
49-
reset your search.
50-
</.styled_link>
51-
</span>
52-
<span :if={String.trim(@filter_text) == "" && Enum.empty?(@funnels)}>
53-
No funnels configured for this site.
54-
</span>
55-
</p>
49+
<.no_search_results :if={@searching?} />
50+
<.empty_state :if={not @searching?} />
5651
<% end %>
5752
</div>
5853
"""
5954
end
55+
56+
defp no_search_results(assigns) do
57+
~H"""
58+
<p class="mt-12 mb-8 text-sm text-center">
59+
No funnels found for this site. Please refine or
60+
<.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
61+
reset your search.
62+
</.styled_link>
63+
</p>
64+
"""
65+
end
66+
67+
defp empty_state(assigns) do
68+
~H"""
69+
<div class="flex flex-col items-center justify-center pt-5 pb-6 max-w-md mx-auto">
70+
<h3 class="text-center text-base font-medium text-gray-900 dark:text-gray-100 leading-7">
71+
Create your first funnel
72+
</h3>
73+
<p class="text-center text-sm mt-1 text-gray-500 dark:text-gray-400 leading-5 text-pretty">
74+
Compose goals into funnels to track user flows and conversion rates.
75+
<.styled_link href="https://plausible.io/docs/funnel-analysis" target="_blank">
76+
Learn more
77+
</.styled_link>
78+
</p>
79+
<.button
80+
id="add-funnel-button"
81+
phx-click="add-funnel"
82+
class="mt-4"
83+
>
84+
Add funnel
85+
</.button>
86+
</div>
87+
"""
88+
end
6089
end

lib/plausible_web/components/billing/billing.ex

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ defmodule PlausibleWeb.Components.Billing do
77
require Plausible.Billing.Subscription.Status
88
alias Plausible.Billing.{Subscription, Subscriptions, Plan, Plans, EnterprisePlan}
99

10-
attr :current_role, :atom, required: true
10+
attr :site, Plausible.Site, required: false, default: nil
11+
attr :current_user, Plausible.Auth.User, required: true
1112
attr :current_team, :any, required: true
1213
attr :locked?, :boolean, required: true
1314
slot :inner_block, required: true
@@ -35,7 +36,7 @@ defmodule PlausibleWeb.Components.Billing do
3536
class="max-w-sm sm:max-w-md mb-2 text-sm text-gray-600 dark:text-gray-100/60 leading-normal text-center"
3637
>
3738
To access this feature,
38-
<.upgrade_call_to_action current_role={@current_role} current_team={@current_team} />
39+
<.upgrade_call_to_action current_user={@current_user} current_team={@current_team} />
3940
</span>
4041
</div>
4142
</div>
@@ -357,8 +358,23 @@ defmodule PlausibleWeb.Components.Billing do
357358
defp change_plan_or_upgrade_text(_subscription), do: "Change plan"
358359

359360
def upgrade_call_to_action(assigns) do
361+
user = assigns.current_user
362+
site = assigns[:site]
360363
team = Plausible.Teams.with_subscription(assigns.current_team)
361364

365+
current_role =
366+
if site do
367+
case Plausible.Teams.Memberships.site_role(site, user) do
368+
{:ok, {_, site_role}} -> site_role
369+
_ -> nil
370+
end
371+
else
372+
if team do
373+
{:ok, team_role} = Plausible.Teams.Memberships.team_role(team, user)
374+
team_role
375+
end
376+
end
377+
362378
upgrade_assistance_required? =
363379
case Plans.get_subscription_plan(team && team.subscription) do
364380
%Plan{kind: :business} -> true
@@ -367,7 +383,7 @@ defmodule PlausibleWeb.Components.Billing do
367383
end
368384

369385
cond do
370-
not is_nil(assigns.current_role) and assigns.current_role not in [:owner, :billing] ->
386+
not is_nil(current_role) and current_role not in [:owner, :billing] ->
371387
~H"ask your team owner to upgrade their subscription."
372388

373389
upgrade_assistance_required? ->

lib/plausible_web/components/billing/notice.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ defmodule PlausibleWeb.Components.Billing.Notice do
6464
end
6565

6666
attr(:current_team, :any, required: true)
67-
attr(:current_role, :atom, required: true)
67+
attr(:current_user, :atom, required: true)
6868
attr(:limit, :integer, required: true)
6969
attr(:resource, :string, required: true)
7070
attr(:rest, :global)
@@ -75,7 +75,7 @@ defmodule PlausibleWeb.Components.Billing.Notice do
7575
{account_label(@current_team)} is limited to {pretty_print_resource_limit(@limit, @resource)}. To increase this limit,
7676
<PlausibleWeb.Components.Billing.upgrade_call_to_action
7777
current_team={@current_team}
78-
current_role={@current_role}
78+
current_user={@current_user}
7979
/>.
8080
</.notice>
8181
"""

lib/plausible_web/components/generic.ex

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,11 @@ defmodule PlausibleWeb.Components.Generic do
485485
slot :subtitle, required: false
486486
attr :feature_mod, :atom, default: nil
487487
attr :feature_toggle?, :boolean, default: false
488-
attr :current_role, :atom, default: nil
489488
attr :current_team, :any, default: nil
490-
attr :site, :any
491-
attr :conn, :any
489+
attr :current_user, :any, default: nil
490+
attr :site, :any, default: nil
491+
attr :conn, :any, default: nil
492+
attr :show_content?, :boolean, default: true
492493

493494
def tile(assigns) do
494495
~H"""
@@ -502,20 +503,24 @@ defmodule PlausibleWeb.Components.Generic do
502503
<div :if={@subtitle != []} class="text-sm mt-px text-gray-500 dark:text-gray-400 leading-5">
503504
{render_slot(@subtitle)}
504505
</div>
505-
<PlausibleWeb.Components.Site.Feature.toggle
506+
507+
<.live_component
506508
:if={@feature_toggle?}
507-
feature_mod={@feature_mod}
509+
module={PlausibleWeb.Components.Site.Feature.ToggleLive}
510+
id={"feature-toggle-#{@site.id}-#{@feature_mod}"}
508511
site={@site}
509-
conn={@conn}
512+
feature_mod={@feature_mod}
513+
current_user={@current_user}
510514
/>
511515
</header>
512-
<div class="border-b dark:border-gray-700 mx-6"></div>
513-
<div class="relative">
516+
<div class={["border-b dark:border-gray-700 mx-6", if(not @show_content?, do: "hidden")]}></div>
517+
<div class={["relative", if(not @show_content?, do: "hidden")]}>
514518
<%= if @feature_mod do %>
515519
<PlausibleWeb.Components.Billing.feature_gate
516520
locked?={@feature_mod.check_availability(@current_team) != :ok}
517-
current_role={@current_role}
521+
current_user={@current_user}
518522
current_team={@current_team}
523+
site={@site}
519524
>
520525
<div class="p-6 pb-14">
521526
{render_slot(@inner_block)}
@@ -1125,6 +1130,16 @@ defmodule PlausibleWeb.Components.Generic do
11251130
"""
11261131
end
11271132

1133+
slot :inner_block, required: true
1134+
1135+
def highlighted(assigns) do
1136+
~H"""
1137+
<span class="font-medium text-indigo-600 dark:text-gray-100">
1138+
{render_slot(@inner_block)}
1139+
</span>
1140+
"""
1141+
end
1142+
11281143
def settings_badge(%{type: :new} = assigns) do
11291144
~H"""
11301145
<span class="inline-block ml-2 bg-indigo-100 text-indigo-600 text-xs font-semibold py-1 px-2 rounded-md">

lib/plausible_web/components/site/feature.ex

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)