+ Set up a few goals like <.highlighted>Signup, <.highlighted>Visit /, or
+ <.highlighted>Scroll 50% on /blog/*
+ first, then return here to build your first funnel.
+
+ <.button_link
+ class="mt-4"
+ href={PlausibleWeb.Router.Helpers.site_path(@socket, :settings_goals, @domain)}
+ >
+ Set up goals →
+
+
+
"""
end
@@ -147,4 +168,8 @@ defmodule PlausibleWeb.Live.FunnelSettings do
def handle_info(:cancel_setup_funnel, socket) do
{:noreply, assign(socket, setup_funnel?: false, funnel_id: nil)}
end
+
+ def handle_info({:feature_toggled, flash_msg, updated_site}, socket) do
+ {:noreply, assign(put_flash(socket, :success, flash_msg), site: updated_site)}
+ end
end
diff --git a/extra/lib/plausible_web/live/funnel_settings/list.ex b/extra/lib/plausible_web/live/funnel_settings/list.ex
index 008756911647..e4c4e642554f 100644
--- a/extra/lib/plausible_web/live/funnel_settings/list.ex
+++ b/extra/lib/plausible_web/live/funnel_settings/list.ex
@@ -10,13 +10,17 @@ defmodule PlausibleWeb.Live.FunnelSettings.List do
use PlausibleWeb, :live_component
def render(assigns) do
+ assigns = assign(assigns, :searching?, String.trim(assigns.filter_text) != "")
+
~H"""
- <.filter_bar filter_text={@filter_text} placeholder="Search Funnels">
- <.button id="add-funnel-button" phx-click="add-funnel" mt?={false}>
- Add funnel
-
-
+ <%= if @searching? or Enum.count(@funnels) > 0 do %>
+ <.filter_bar filter_text={@filter_text} placeholder="Search Funnels">
+ <.button id="add-funnel-button" phx-click="add-funnel" mt?={false}>
+ Add funnel
+
+
+ <% end %>
<%= if Enum.count(@funnels) > 0 do %>
<.table rows={@funnels}>
@@ -42,19 +46,44 @@ defmodule PlausibleWeb.Live.FunnelSettings.List do
<% else %>
-
-
- No funnels found for this site. Please refine or
- <.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
- reset your search.
-
-
-
- No funnels configured for this site.
-
-
"""
end
+
+ defp no_search_results(assigns) do
+ ~H"""
+
+ No funnels found for this site. Please refine or
+ <.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
+ reset your search.
+
+
+ """
+ end
+
+ defp empty_state(assigns) do
+ ~H"""
+
+
+ Create your first funnel
+
+
+ Compose goals into funnels to track user flows and conversion rates.
+ <.styled_link href="https://plausible.io/docs/funnel-analysis" target="_blank">
+ Learn more
+
+
-
- No goals found for this site. Please refine or
- <.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
- reset your search.
-
-
-
- No goals configured for this site.
-
-
"""
end
+ defp no_search_results(assigns) do
+ ~H"""
+
+ No goals found for this site. Please refine or
+ <.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
+ reset your search.
+
+
+ """
+ end
+
+ defp empty_state(assigns) do
+ ~H"""
+
+
+ Create your first goal
+
+
+ Define actions that you want your users to take, like visiting a certain page, submitting a form, etc.
+ <.styled_link href="https://plausible.io/docs/goal-conversions" target="_blank">
+ Learn more
+
+
-
- <.td actions>
- <.delete_button
- href={"/#{URI.encode_www_form(@site.domain)}/settings/forget-import/#{entry.site_import.id}"}
- method="delete"
- data-confirm="Are you sure you want to delete this import?"
+ <.tile docs="google-analytics-import">
+ <:title>
+ Import data
+
+ <:subtitle :if={not Enum.empty?(@site_imports)}>
+ Import data from external sources. Up to {Plausible.Imported.max_complete_imports()} imports are allowed at a time.
+
+ <%= if Enum.empty?(@site_imports) do %>
+
+
+ Import your first data
+
+
+ Import data from external sources. Up to {Plausible.Imported.max_complete_imports()} imports are allowed at a time.
+
+
+ <.button_link
+ theme="secondary"
+ href={Plausible.Google.API.import_authorize_url(@site.id)}
+ disabled={@import_in_progress? or @at_maximum?}
+ mt?={false}
+ >
+ Import from
+
+
+ <.button_link
+ disabled={@import_in_progress? or @at_maximum?}
+ href={"/#{URI.encode_www_form(@site.domain)}/settings/import"}
+ mt?={false}
+ >
+ Import from CSV
+
+
- <.filter_bar filter_text={@filter_text} placeholder="Search Properties">
- <.button phx-click="add-prop" mt?={false}>
- Add property
-
-
- <%= if is_list(@props) && length(@props) > 0 do %>
+ <%= if @searching? or Enum.count(@props) > 0 do %>
+ <.filter_bar filter_text={@filter_text} placeholder="Search Properties">
+ <.button phx-click="add-prop" mt?={false}>
+ Add property
+
+
+ <% end %>
+
+ <%= if Enum.count(@props) > 0 do %>
<.table id="allowed-props" rows={Enum.with_index(@props)}>
<:tbody :let={{prop, index}}>
<.td id={"prop-#{index}"}>{prop}
@@ -32,22 +37,47 @@ defmodule PlausibleWeb.Live.PropsSettings.List do
<% else %>
-
-
- No properties found for this site. Please refine or
- <.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
- reset your search.
-
-
-
- No properties configured for this site.
-
-
"""
end
+ defp no_search_results(assigns) do
+ ~H"""
+
+ No properties found for this site. Please refine or
+ <.styled_link phx-click="reset-filter-text" id="reset-filter-hint">
+ reset your search.
+
+
+ """
+ end
+
+ defp empty_state(assigns) do
+ ~H"""
+
+
+ Create a custom property
+
+
+ Attach custom properties when sending a pageview or an event to create custom metrics.
+ <.styled_link href="https://plausible.io/docs/custom-props/introduction" target="_blank">
+ Learn more
+
+
+ """
+ end
+
defp delete_confirmation_text(prop) do
"""
Are you sure you want to remove the following property:
diff --git a/lib/plausible_web/live/shared_link_settings.ex b/lib/plausible_web/live/shared_link_settings.ex
index 3ebf4ea5c335..110d12bcef77 100644
--- a/lib/plausible_web/live/shared_link_settings.ex
+++ b/lib/plausible_web/live/shared_link_settings.ex
@@ -41,77 +41,111 @@ defmodule PlausibleWeb.Live.SharedLinkSettings do
-
- <.table rows={@shared_links} id="shared-links-table">
- <:thead>
- <.th hide_on_mobile>Name
- <.th>Link
- <.th invisible>Actions
-
- <:tbody :let={link}>
- <.td truncate hide_on_mobile>
- {link.name}
-
-
-
- <.td>
- <.input_with_clipboard
- name={link.slug}
- id={link.slug}
- value={Plausible.Sites.shared_link_url(@site, link)}
- />
-
- <.td actions>
- <.edit_button
- class="mt-1"
- phx-click="edit-shared-link"
- phx-value-slug={link.slug}
- />
- <.delete_button
- class="mt-1"
- phx-click="delete-shared-link"
- phx-value-slug={link.slug}
- data-confirm="Are you sure you want to delete this shared link? The stats will not be accessible with this link anymore."
- />
-
-
-
+ <.live_component
+ module={PlausibleWeb.Live.SharedLinkSettings.Form}
+ id={"shared-links-form-#{modal_unique_id}"}
+ context_unique_id={modal_unique_id}
+ site={@site}
+ shared_link={@form_shared_link}
+ on_save_shared_link={
+ fn shared_link, socket ->
+ send(self(), {:shared_link_added, shared_link})
+ Modal.close(socket, "shared-links-form-modal")
+ end
+ }
+ />
+
+
+ <%= if Enum.empty?(@shared_links) do %>
+
+
+ Create your first shared link
+
+
+ Share your stats privately with anyone. Links are unique, secure, and can be password-protected.
+ <.styled_link href="https://plausible.io/docs/shared-links" target="_blank">
+ Learn more
+
+
+ <% end %>
<.live_component :let={modal_unique_id} module={Modal} id="country-rule-form-modal">
<.form
diff --git a/lib/plausible_web/live/shields/hostname_rules.ex b/lib/plausible_web/live/shields/hostname_rules.ex
index dbb4565bdf84..3f355e69e420 100644
--- a/lib/plausible_web/live/shields/hostname_rules.ex
+++ b/lib/plausible_web/live/shields/hostname_rules.ex
@@ -34,85 +34,109 @@ defmodule PlausibleWeb.Live.Shields.HostnameRules do
<.settings_tiles>
<.tile docs="excluding#exclude-visits-by-hostname">
<:title>Hostnames allow list
- <:subtitle>Accept incoming traffic only from familiar hostnames.
- <.filter_bar
- :if={@hostname_rules_count < Shields.maximum_hostname_rules()}
- filtering_enabled?={false}
- >
- <.button
- id="add-hostname-rule"
- x-data
- x-on:click={Modal.JS.open("hostname-rule-form-modal")}
- mt?={false}
- >
- Add hostname
-
-
+ <:subtitle :if={not Enum.empty?(@hostname_rules)}>
+ Accept incoming traffic only from familiar hostnames.
+
- <.notice
- :if={@hostname_rules_count >= Shields.maximum_hostname_rules()}
- class="mt-4"
- title="Maximum number of hostnames reached"
- theme={:gray}
- >
-
- You've reached the maximum number of hostnames you can block ({Shields.maximum_hostname_rules()}). Please remove one before adding another.
-
-
+ <%= if Enum.empty?(@hostname_rules) do %>
+
+
+ Allow a hostname
+
+
+ Accept incoming traffic only from familiar hostnames. Traffic from all hostnames is recorded until you add your first rule.
+ <.styled_link
+ href="https://plausible.io/docs/excluding#exclude-visits-by-hostname"
+ target="_blank"
+ >
+ Learn more
+
+
- No sites found. Please search for something else.
+
+ No sites found. Try a different search term.
-
-
- You currently have no personal sites. Are you looking for your team’s sites?
- <.styled_link href={Routes.auth_path(@socket, :select_team)}>
- Go to your team →
-
-
+
+ {@empty_state_title}
+
+
+ {@empty_state_description}
+
+
+ <.button_link
+ href={"/sites/new?flow=#{PlausibleWeb.Flows.provisioning()}"}
+ theme="primary"
+ mt?={false}
+ >
+ Add website
+
+ <.button_link
+ :if={not Teams.setup?(@current_team) and @has_sites?}
+ href={Routes.auth_path(@socket, :select_team)}
+ theme="secondary"
+ mt?={false}
+ >
+ Go to team sites
+
+
+
<.consolidated_view_card_cta
:if={
- @filter_text == "" and
+ not @searching? and
!@consolidated_view and @no_consolidated_view_reason not in [:no_sites, :unavailable] and
not @consolidated_view_cta_dismissed?
}
@@ -156,7 +200,7 @@ defmodule PlausibleWeb.Live.Sites do
/>
<.consolidated_view_card
:if={
- @filter_text == "" and not is_nil(@consolidated_view) and
+ not @searching? and not is_nil(@consolidated_view) and
consolidated_view_ok_to_display?(@current_team)
}
can_manage_consolidated_view?={@can_manage_consolidated_view?}
diff --git a/lib/plausible_web/live/team_management.ex b/lib/plausible_web/live/team_management.ex
index 1290c14ce776..77b74561968b 100644
--- a/lib/plausible_web/live/team_management.ex
+++ b/lib/plausible_web/live/team_management.ex
@@ -43,7 +43,7 @@ defmodule PlausibleWeb.Live.TeamManagement do
diff --git a/lib/plausible_web/router.ex b/lib/plausible_web/router.ex
index 03c869400e1a..a5046072e320 100644
--- a/lib/plausible_web/router.ex
+++ b/lib/plausible_web/router.ex
@@ -703,10 +703,6 @@ defmodule PlausibleWeb.Router do
get "/:domain/settings/properties", SiteController, :settings_props
get "/:domain/settings/email-reports", SiteController, :settings_email_reports
- put "/:domain/settings/features/visibility/:setting",
- SiteController,
- :update_feature_visibility
-
put "/:domain/settings", SiteController, :update_settings
get "/:domain/export", StatsController, :csv_export
diff --git a/lib/plausible_web/templates/settings/api_keys.html.heex b/lib/plausible_web/templates/settings/api_keys.html.heex
index a5540ab9e6f1..04cd79b67c6d 100644
--- a/lib/plausible_web/templates/settings/api_keys.html.heex
+++ b/lib/plausible_web/templates/settings/api_keys.html.heex
@@ -1,63 +1,74 @@
<.settings_tiles>
<.tile
docs="stats-api"
- current_role={@current_team_role}
+ current_user={@current_user}
current_team={@current_team}
feature_mod={Plausible.Billing.Feature.StatsAPI}
>
<:title>
API keys
- <:subtitle>
+ <:subtitle :if={not Enum.empty?(@api_keys)}>
Create and manage access.
- <.filter_bar filtering_enabled?={false}>
- <.button_link mt?={false} href={Routes.settings_path(@conn, :new_api_key)}>
- New API Key
-
-
+ <%= if Enum.empty?(@api_keys) do %>
+
+
+ Create your first API key
+
+
+ Access your stats through the Plausible API.
+ <.styled_link href="https://plausible.io/docs/stats-api">Learn more
+
+ <.button_link href={Routes.settings_path(@conn, :new_api_key)}>
+ New API Key
+
+
+ <% else %>
+ <.filter_bar filtering_enabled?={false}>
+ <.button_link mt?={false} href={Routes.settings_path(@conn, :new_api_key)}>
+ New API Key
+
+
-
diff --git a/lib/plausible_web/templates/site/settings_visibility.html.heex b/lib/plausible_web/templates/site/settings_visibility.html.heex
index 05bc17b5961a..cf1cd9c86141 100644
--- a/lib/plausible_web/templates/site/settings_visibility.html.heex
+++ b/lib/plausible_web/templates/site/settings_visibility.html.heex
@@ -27,33 +27,17 @@
- <.tile
- docs="shared-links"
- feature_mod={Plausible.Billing.Feature.SharedLinks}
- site={@site}
- current_role={@site_role}
- current_team={@site_team}
- conn={@conn}
- >
- <:title>
- Shared links
-
- <:subtitle>
- You can share your stats privately by generating a shared link. The links are impossible to guess and you can add password protection for extra security.
-
-
-
<.tile
docs="embed-dashboard"
feature_mod={Plausible.Billing.Feature.SharedLinks}
site={@site}
- current_role={@site_role}
+ current_user={@current_user}
current_team={@site_team}
conn={@conn}
>
diff --git a/test/plausible_web/components/billing/billing_test.exs b/test/plausible_web/components/billing/billing_test.exs
index fff310ebb949..dd5154644bde 100644
--- a/test/plausible_web/components/billing/billing_test.exs
+++ b/test/plausible_web/components/billing/billing_test.exs
@@ -11,7 +11,7 @@ defmodule PlausibleWeb.Components.BillingTest do
test "renders a blur overlay if the feature is locked", %{user: user} do
html =
%{
- current_role: :owner,
+ current_user: user,
current_team: user |> subscribe_to_growth_plan() |> team_of(),
locked?: true
}
@@ -22,10 +22,10 @@ defmodule PlausibleWeb.Components.BillingTest do
assert text_of_element(html, "#feature-gate-overlay") =~ "Upgrade to unlock"
end
- test "renders a blur overlay for a teamless account" do
+ test "renders a blur overlay for a teamless account", %{user: user} do
html =
%{
- current_role: nil,
+ current_user: user,
current_team: nil,
locked?: true
}
@@ -39,7 +39,7 @@ defmodule PlausibleWeb.Components.BillingTest do
test "does not render a blur overlay if feature access is granted", %{user: user} do
html =
%{
- current_role: :owner,
+ current_user: user,
current_team: user |> subscribe_to_business_plan() |> team_of(),
locked?: false
}
@@ -52,7 +52,7 @@ defmodule PlausibleWeb.Components.BillingTest do
test "renders upgrade cta linking to the upgrade page if user role is :owner", %{user: user} do
html =
%{
- current_role: :owner,
+ current_user: user,
current_team: user |> subscribe_to_growth_plan() |> team_of(),
locked?: true
}
@@ -62,10 +62,13 @@ defmodule PlausibleWeb.Components.BillingTest do
end
test "renders upgrade cta linking to the upgrade page if user role is :billing", %{user: user} do
+ team = user |> subscribe_to_growth_plan() |> team_of()
+ billing = add_member(team, role: :billing)
+
html =
%{
- current_role: :billing,
- current_team: user |> subscribe_to_growth_plan() |> team_of(),
+ current_user: billing,
+ current_team: team,
locked?: true
}
|> render_feature_gate()
@@ -77,10 +80,13 @@ defmodule PlausibleWeb.Components.BillingTest do
%{
user: user
} do
+ team = user |> subscribe_to_growth_plan() |> team_of()
+ editor = add_member(team, role: :editor)
+
html =
%{
- current_role: :editor,
- current_team: user |> subscribe_to_growth_plan() |> team_of(),
+ current_user: editor,
+ current_team: team,
locked?: true
}
|> render_feature_gate()
diff --git a/test/plausible_web/components/billing/notice_test.exs b/test/plausible_web/components/billing/notice_test.exs
index cdf9dc63bae2..a6d13ee9956c 100644
--- a/test/plausible_web/components/billing/notice_test.exs
+++ b/test/plausible_web/components/billing/notice_test.exs
@@ -5,12 +5,12 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
alias PlausibleWeb.Components.Billing.Notice
test "limit_exceeded/1 when user is on growth displays upgrade link" do
- me = new_user() |> subscribe_to_growth_plan()
- team = team_of(me)
+ user = new_user() |> subscribe_to_growth_plan()
+ team = team_of(user)
rendered =
render_component(&Notice.limit_exceeded/1,
- current_role: :owner,
+ current_user: user,
current_team: team,
limit: 10,
resource: "users"
@@ -22,12 +22,12 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
end
test "limit_exceeded/1 prints resource in singular case when limit is 1" do
- me = new_user() |> subscribe_to_growth_plan()
+ user = new_user() |> subscribe_to_growth_plan()
rendered =
render_component(&Notice.limit_exceeded/1,
- current_role: :owner,
- current_team: team_of(me),
+ current_user: user,
+ current_team: team_of(user),
limit: 1,
resource: "users"
)
@@ -38,13 +38,14 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
end
test "limit_exceeded/1 when current team role is non-owner" do
- me = new_user() |> subscribe_to_growth_plan()
- my_team = team_of(me) |> Plausible.Teams.complete_setup()
+ user = new_user() |> subscribe_to_growth_plan()
+ team = team_of(user) |> Plausible.Teams.complete_setup()
+ editor = add_member(team, role: :editor)
rendered =
render_component(&Notice.limit_exceeded/1,
- current_role: :editor,
- current_team: my_team,
+ current_user: editor,
+ current_team: team,
limit: 10,
resource: "users"
)
@@ -55,12 +56,12 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
@tag :ee_only
test "limit_exceeded/1 when user is on trial displays upgrade link" do
- me = new_user(trial_expiry_date: Date.utc_today())
+ user = new_user(trial_expiry_date: Date.utc_today())
rendered =
render_component(&Notice.limit_exceeded/1,
- current_role: :owner,
- current_team: team_of(me),
+ current_user: user,
+ current_team: team_of(user),
limit: 10,
resource: "users"
)
@@ -72,12 +73,12 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
@tag :ee_only
test "limit_exceeded/1 when user is on an enterprise plan displays support email" do
- me = new_user() |> subscribe_to_enterprise_plan()
+ user = new_user() |> subscribe_to_enterprise_plan()
rendered =
render_component(&Notice.limit_exceeded/1,
- current_role: :owner,
- current_team: team_of(me),
+ current_user: user,
+ current_team: team_of(user),
limit: 10,
resource: "users"
)
@@ -90,12 +91,12 @@ defmodule PlausibleWeb.Components.Billing.NoticeTest do
@tag :ee_only
test "limit_exceeded/1 when user is on a business plan displays support email" do
- me = new_user() |> subscribe_to_business_plan()
- team = team_of(me)
+ user = new_user() |> subscribe_to_business_plan()
+ team = team_of(user)
rendered =
render_component(&Notice.limit_exceeded/1,
- current_role: :owner,
+ current_user: user,
current_team: team,
limit: 10,
resource: "users"
diff --git a/test/plausible_web/controllers/site_controller_test.exs b/test/plausible_web/controllers/site_controller_test.exs
index aa28867508d1..9ff1561f026f 100644
--- a/test/plausible_web/controllers/site_controller_test.exs
+++ b/test/plausible_web/controllers/site_controller_test.exs
@@ -57,9 +57,77 @@ defmodule PlausibleWeb.SiteControllerTest do
describe "GET /sites" do
setup [:create_user, :log_in]
- test "shows empty screen if no sites", %{conn: conn} do
+ test "shows personal sites empty state when there are no sites at all", %{conn: conn} do
conn = get(conn, "/sites")
- assert html_response(conn, 200) =~ "You don't have any sites yet"
+ resp = html_response(conn, 200)
+
+ assert resp =~ "Add your first personal site"
+ assert resp =~ "Collect simple, privacy-friendly stats to better understand your audience."
+ refute resp =~ "Go to team sites"
+ end
+
+ test "shows team sites empty state when team is setup and there are no sites at all", %{
+ conn: conn,
+ user: user
+ } do
+ {:ok, team} = Teams.get_or_create(user)
+ team = Teams.complete_setup(team)
+ conn = set_current_team(conn, team)
+
+ conn = get(conn, "/sites")
+ resp = html_response(conn, 200)
+
+ assert resp =~ "Add your first team site"
+ assert resp =~ "Collect simple, privacy-friendly stats to better understand your audience."
+ refute resp =~ "Go to team sites"
+ end
+
+ test "shows team sites empty state when team is setup but has no team sites, and user has personal sites",
+ %{conn: conn, user: user} do
+ _personal_site = new_site(owner: user)
+
+ other_user = new_user()
+ {:ok, other_team} = Teams.get_or_create(other_user)
+ other_team = Teams.complete_setup(other_team)
+ add_member(other_team, user: user, role: :admin)
+ conn = set_current_team(conn, other_team)
+
+ conn = get(conn, "/sites")
+ resp = html_response(conn, 200)
+
+ assert resp =~ "Add your first team site"
+ assert resp =~ "Collect simple, privacy-friendly stats to better understand your audience."
+ refute resp =~ "Go to team sites"
+ end
+
+ test "shows personal sites empty state when there are team sites but no personal sites", %{
+ conn: conn,
+ user: user
+ } do
+ {:ok, team} = Teams.get_or_create(user)
+ team = Teams.complete_setup(team)
+ _team_site = new_site(team: team)
+
+ conn = get(conn, "/sites")
+ resp = html_response(conn, 200)
+
+ assert resp =~ "Add your first personal site"
+ assert resp =~ "Collect simple, privacy-friendly stats to better understand your audience."
+ assert resp =~ "Go to team sites"
+ end
+
+ test "shows empty search state when filter returns no results but there are sites", %{
+ conn: conn,
+ user: user
+ } do
+ _site = new_site(domain: "example.com", owner: user)
+
+ conn = get(conn, "/sites", filter_text: "nonexistent")
+ resp = html_response(conn, 200)
+
+ assert resp =~ "No sites found. Try a different search term."
+ refute resp =~ "Add your first"
+ refute resp =~ "Go to team sites"
end
test "lists all of your sites with last 24h visitors (defaulting to 0 on first mount)", %{
@@ -195,7 +263,7 @@ defmodule PlausibleWeb.SiteControllerTest do
resp = html_response(conn, 200)
refute resp =~ "second.example.com"
- assert html_response(conn, 200) =~ "No sites found. Please search for something else."
+ assert html_response(conn, 200) =~ "No sites found. Try a different search term."
refute html_response(conn, 200) =~ "You don't have any sites yet."
end
@@ -776,7 +844,7 @@ defmodule PlausibleWeb.SiteControllerTest do
conn = get(conn, "/#{site.domain}/settings/visibility")
resp = html_response(conn, 200)
- assert resp =~ "No shared links configured for this site"
+ assert resp =~ "Create your first shared link"
end
test "does not render shared links with special names", %{conn: conn, site: site} do
@@ -990,7 +1058,7 @@ defmodule PlausibleWeb.SiteControllerTest do
assert element_exists?(resp, ~s|a[href^="https://accounts.google.com/o/oauth2/"]|)
assert(resp =~ "Import data")
- assert resp =~ "There are no imports yet"
+ assert resp =~ "Import your first data"
assert resp =~ "Export data"
end
@@ -1258,123 +1326,6 @@ defmodule PlausibleWeb.SiteControllerTest do
end
end
- describe "PUT /:domain/settings/features/visibility/:setting" do
- def query_conn_with_some_url(context) do
- {:ok, Map.put(context, :conn_with_url, get(context.conn, "/some_parent_path"))}
- end
-
- setup [:create_user, :log_in, :query_conn_with_some_url]
-
- for {title, setting} <- %{
- "Goals" => :conversions_enabled,
- "Funnels" => :funnels_enabled,
- "Custom Properties" => :props_enabled
- } do
- test "can toggle #{title} with admin access", %{
- user: user,
- conn: conn0,
- conn_with_url: conn_with_url
- } do
- site = new_site()
- add_guest(site, user: user, role: :editor)
-
- conn =
- put(
- conn0,
- PlausibleWeb.Components.Site.Feature.target(
- site,
- unquote(setting),
- conn_with_url,
- false
- )
- )
-
- assert Phoenix.Flash.get(conn.assigns.flash, :success) ==
- "#{unquote(title)} are now hidden from your dashboard"
-
- assert redirected_to(conn, 302) =~ "/some_parent_path"
-
- assert %{unquote(setting) => false} = Plausible.Sites.get_by_domain(site.domain)
-
- conn =
- put(
- conn0,
- PlausibleWeb.Components.Site.Feature.target(
- site,
- unquote(setting),
- conn_with_url,
- true
- )
- )
-
- assert Phoenix.Flash.get(conn.assigns.flash, :success) ==
- "#{unquote(title)} are now visible again on your dashboard"
-
- assert redirected_to(conn, 302) =~ "/some_parent_path"
-
- assert %{unquote(setting) => true} = Plausible.Sites.get_by_domain(site.domain)
- end
- end
-
- for {title, setting} <- %{
- "Goals" => :conversions_enabled,
- "Funnels" => :funnels_enabled,
- "Properties" => :props_enabled
- } do
- test "cannot toggle #{title} with viewer access", %{
- user: user,
- conn: conn0,
- conn_with_url: conn_with_url
- } do
- site = new_site()
- add_guest(site, user: user, role: :viewer)
-
- conn =
- put(
- conn0,
- PlausibleWeb.Components.Site.Feature.target(
- site,
- unquote(setting),
- conn_with_url,
- false
- )
- )
-
- assert conn.status == 404
- assert conn.halted
- end
- end
-
- test "setting feature visibility is idempotent", %{
- user: user,
- conn: conn0,
- conn_with_url: conn_with_url
- } do
- site = new_site()
- add_guest(site, user: user, role: :editor)
-
- setting = :funnels_enabled
-
- conn =
- put(
- conn0,
- PlausibleWeb.Components.Site.Feature.target(site, setting, conn_with_url, false)
- )
-
- assert %{^setting => false} = Plausible.Sites.get_by_domain(site.domain)
- assert redirected_to(conn, 302) =~ "/some_parent_path"
-
- conn =
- put(
- conn0,
- PlausibleWeb.Components.Site.Feature.target(site, setting, conn_with_url, false)
- )
-
- assert %{^setting => false} = Plausible.Sites.get_by_domain(site.domain)
- assert redirected_to(conn, 302) =~ "/some_parent_path"
- end
- end
-
describe "POST /sites/:domain/weekly-report/enable" do
setup [:create_user, :log_in, :create_site]
diff --git a/test/plausible_web/live/funnel_settings_test.exs b/test/plausible_web/live/funnel_settings_test.exs
index f3142b0618e1..baf344472262 100644
--- a/test/plausible_web/live/funnel_settings_test.exs
+++ b/test/plausible_web/live/funnel_settings_test.exs
@@ -38,7 +38,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
end
test "search funnels input is rendered", %{conn: conn, site: site} do
- setup_goals(site)
+ {:ok, _} = setup_funnels(site)
conn = get(conn, "/#{site.domain}/settings/funnels")
resp = html_response(conn, 200)
assert element_exists?(resp, ~s/input[type="text"]#filter-text/)
@@ -77,7 +77,7 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
conn = get(conn, "/#{site.domain}/settings/funnels")
doc = conn |> html_response(200)
- assert text(doc) =~ "Set up a few goals first"
+ assert text(doc) =~ "Set up a few goals"
add_goals_path = Routes.site_path(conn, :settings_goals, site.domain)
assert element_exists?(doc, ~s/a[href="#{add_goals_path}"]/)
@@ -90,6 +90,16 @@ defmodule PlausibleWeb.Live.FunnelSettingsTest do
describe "FunnelSettings live view" do
setup [:create_user, :log_in, :create_site]
+ test "allows dashboard toggle", %{conn: conn, site: site} do
+ lv = get_liveview(conn, site)
+ lv |> element("#feature-funnels-toggle button") |> render_click()
+ assert render(lv) =~ "Funnels are now hidden from your dashboard"
+ assert Plausible.Billing.Feature.Funnels.opted_out?(Plausible.Repo.reload!(site))
+ lv |> element("#feature-funnels-toggle button") |> render_click()
+ assert render(lv) =~ "Funnels are now visible again on your dashboard"
+ refute Plausible.Billing.Feature.Funnels.opted_out?(Plausible.Repo.reload!(site))
+ end
+
test "allows list filtering / search", %{conn: conn, site: site} do
{:ok, _} = setup_funnels(site, ["Funnel One", "Search Me"])
{lv, html} = get_liveview(conn, site, with_html?: true)
diff --git a/test/plausible_web/live/goal_settings_test.exs b/test/plausible_web/live/goal_settings_test.exs
index aa4d6a6fe792..d869c544ff78 100644
--- a/test/plausible_web/live/goal_settings_test.exs
+++ b/test/plausible_web/live/goal_settings_test.exs
@@ -76,7 +76,7 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
test "if no goals are present, a proper info is displayed", %{conn: conn, site: site} do
conn = get(conn, "/#{site.domain}/settings/goals")
resp = html_response(conn, 200)
- assert resp =~ "No goals configured for this site"
+ assert resp =~ "Create your first goal"
end
test "if goals are present, no info about missing goals is displayed", %{
@@ -86,7 +86,7 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
{:ok, _goals} = setup_goals(site)
conn = get(conn, "/#{site.domain}/settings/goals")
resp = html_response(conn, 200)
- refute resp =~ "No goals configured for this site"
+ refute resp =~ "Create your first goal"
end
test "add goal button is rendered", %{conn: conn, site: site} do
@@ -96,6 +96,7 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
end
test "search goals input is rendered", %{conn: conn, site: site} do
+ {:ok, _goals} = setup_goals(site)
conn = get(conn, "/#{site.domain}/settings/goals")
resp = html_response(conn, 200)
assert element_exists?(resp, ~s/input[type="text"]#filter-text/)
@@ -119,7 +120,7 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
assert resp = html_response(conn, 200)
assert resp =~ "Define actions that you want your users to take"
- assert resp =~ "No goals configured for this site"
+ assert resp =~ "Create your first goal"
assert element_exists?(resp, ~s|a[href="https://plausible.io/docs/goal-conversions"]|)
end
@@ -151,6 +152,16 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
describe "GoalSettings live view" do
setup [:create_user, :log_in, :create_site]
+ test "allows dashboard toggle", %{conn: conn, site: site} do
+ lv = get_liveview(conn, site)
+ lv |> element("#feature-goals-toggle button") |> render_click()
+ assert render(lv) =~ "Goals are now hidden from your dashboard"
+ assert Plausible.Billing.Feature.Goals.opted_out?(Plausible.Repo.reload!(site))
+ lv |> element("#feature-goals-toggle button") |> render_click()
+ assert render(lv) =~ "Goals are now visible again on your dashboard"
+ refute Plausible.Billing.Feature.Goals.opted_out?(Plausible.Repo.reload!(site))
+ end
+
test "allows goal deletion", %{conn: conn, site: site} do
{:ok, [g1, g2 | _]} = setup_goals(site)
{lv, html} = get_liveview(conn, site, with_html?: true)
diff --git a/test/plausible_web/live/props_settings_test.exs b/test/plausible_web/live/props_settings_test.exs
index dd1e5df04def..d90fdffe6989 100644
--- a/test/plausible_web/live/props_settings_test.exs
+++ b/test/plausible_web/live/props_settings_test.exs
@@ -75,7 +75,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
test "if no props are allowed, a proper info is displayed", %{conn: conn, site: site} do
conn = get(conn, "/#{site.domain}/settings/properties")
resp = html_response(conn, 200)
- assert resp =~ "No properties configured for this site"
+ assert resp =~ "Create a custom property"
end
test "if props are enabled, no info about missing props is displayed", %{
@@ -85,7 +85,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
{:ok, site} = Plausible.Props.allow(site, ["amount", "logged_in", "is_customer"])
conn = get(conn, "/#{site.domain}/settings/properties")
resp = html_response(conn, 200)
- refute resp =~ "No properties configured for this site"
+ refute resp =~ "Create a custom property"
end
test "add property button is rendered", %{conn: conn, site: site} do
@@ -95,6 +95,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
end
test "search props input is rendered", %{conn: conn, site: site} do
+ {:ok, site} = Plausible.Props.allow(site, ["amount", "logged_in", "is_customer"])
conn = get(conn, "/#{site.domain}/settings/properties")
resp = html_response(conn, 200)
assert element_exists?(resp, ~s/input[type="text"]#filter-text/)
@@ -142,13 +143,16 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
} do
conn = get(conn, "/#{consolidated_view.domain}/settings/properties")
resp = html_response(conn, 200)
- assert resp =~ "No properties configured for this site"
+ assert resp =~ "Create a custom property"
end
test "add property button and search input are rendered", %{
conn: conn,
consolidated_view: consolidated_view
} do
+ {:ok, consolidated_view} =
+ Plausible.Props.allow(consolidated_view, ["amount", "logged_in", "is_customer"])
+
conn = get(conn, "/#{consolidated_view.domain}/settings/properties")
resp = html_response(conn, 200)
assert element_exists?(resp, ~s/button[phx-click="add-prop"]/)
@@ -158,19 +162,19 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
end
end
- # validating input
- # clicking suggestions fills out input
- # adding props
- # error when reached props limit
- # clearserror when fixed input
- # removal
- # removal shows confirmation
- # allow existing props: shows/hides
- # after adding all suggestions no allow existing props
-
describe "PropsSettings live view" do
setup [:create_user, :log_in, :create_site]
+ test "allows dashboard toggle", %{conn: conn, site: site} do
+ lv = get_liveview(conn, site)
+ lv |> element("#feature-props-toggle button") |> render_click()
+ assert render(lv) =~ "Custom Properties are now hidden from your dashboard"
+ assert Plausible.Billing.Feature.Props.opted_out?(Plausible.Repo.reload!(site))
+ lv |> element("#feature-props-toggle button") |> render_click()
+ assert render(lv) =~ "Custom Properties are now visible again on your dashboard"
+ refute Plausible.Billing.Feature.Props.opted_out?(Plausible.Repo.reload!(site))
+ end
+
test "allows prop removal", %{conn: conn, site: site} do
{:ok, site} = Plausible.Props.allow(site, ["amount", "logged_in"])
{lv, html} = get_liveview(conn, site, with_html?: true)
@@ -222,6 +226,7 @@ defmodule PlausibleWeb.Live.PropsSettingsTest do
end
test "allows resetting filter text via no match link", %{conn: conn, site: site} do
+ {:ok, site} = Plausible.Props.allow(site, ["amount", "logged_in", "is_customer"])
lv = get_liveview(conn, site)
html = type_into_search(lv, "Definitely this is not going to render any matches")
diff --git a/test/plausible_web/live/shared_link_settings_test.exs b/test/plausible_web/live/shared_link_settings_test.exs
index 8e79d95f7a00..3841b4f75d46 100644
--- a/test/plausible_web/live/shared_link_settings_test.exs
+++ b/test/plausible_web/live/shared_link_settings_test.exs
@@ -101,7 +101,7 @@ defmodule PlausibleWeb.Live.SharedLinkSettingsTest do
lv = get_liveview(conn, session)
html = render(lv)
- assert html =~ "No shared links configured for this site"
+ assert html =~ "Create your first shared link"
end
end
diff --git a/test/plausible_web/live/shields/countries_test.exs b/test/plausible_web/live/shields/countries_test.exs
index ecd98da8db8c..f0975089320e 100644
--- a/test/plausible_web/live/shields/countries_test.exs
+++ b/test/plausible_web/live/shields/countries_test.exs
@@ -13,7 +13,7 @@ defmodule PlausibleWeb.Live.Shields.CountriesTest do
conn = get(conn, "/#{site.domain}/settings/shields/countries")
resp = html_response(conn, 200)
- assert resp =~ "No country rules configured for this site"
+ assert resp =~ "Block a country"
assert resp =~ "Country block list"
end
diff --git a/test/plausible_web/live/shields/hostnames_test.exs b/test/plausible_web/live/shields/hostnames_test.exs
index 497162bbaae1..22c150dc8fbf 100644
--- a/test/plausible_web/live/shields/hostnames_test.exs
+++ b/test/plausible_web/live/shields/hostnames_test.exs
@@ -13,9 +13,9 @@ defmodule PlausibleWeb.Live.Shields.HostnamesTest do
conn = get(conn, "/#{site.domain}/settings/shields/hostnames")
resp = html_response(conn, 200)
- assert resp =~ "No hostname rules configured for this site"
+ assert resp =~ "Allow a hostname"
assert resp =~ "Hostnames allow list"
- assert resp =~ "Traffic from all hostnames is currently accepted."
+ assert resp =~ "Traffic from all hostnames is recorded until you add your first rule"
end
test "lists hostname rules with remove actions", %{conn: conn, site: site} do
diff --git a/test/plausible_web/live/shields/ip_addresses_test.exs b/test/plausible_web/live/shields/ip_addresses_test.exs
index f5c960ff7ffa..2e044c51220c 100644
--- a/test/plausible_web/live/shields/ip_addresses_test.exs
+++ b/test/plausible_web/live/shields/ip_addresses_test.exs
@@ -13,7 +13,7 @@ defmodule PlausibleWeb.Live.Shields.IPAddressesTest do
conn = get(conn, "/#{site.domain}/settings/shields/ip_addresses")
resp = html_response(conn, 200)
- assert resp =~ "No IP rules configured for this site"
+ assert resp =~ "Block an IP address"
assert resp =~ "IP block list"
end
diff --git a/test/plausible_web/live/shields/pages_test.exs b/test/plausible_web/live/shields/pages_test.exs
index a97c774f9eae..acc5d3eb3158 100644
--- a/test/plausible_web/live/shields/pages_test.exs
+++ b/test/plausible_web/live/shields/pages_test.exs
@@ -13,7 +13,7 @@ defmodule PlausibleWeb.Live.Shields.PagesTest do
conn = get(conn, "/#{site.domain}/settings/shields/pages")
resp = html_response(conn, 200)
- assert resp =~ "No page rules configured for this site"
+ assert resp =~ "Block a page"
assert resp =~ "Pages block list"
end
diff --git a/test/plausible_web/live/sites_test.exs b/test/plausible_web/live/sites_test.exs
index a07dcba03451..afb14d696c57 100644
--- a/test/plausible_web/live/sites_test.exs
+++ b/test/plausible_web/live/sites_test.exs
@@ -14,10 +14,10 @@ defmodule PlausibleWeb.Live.SitesTest do
{:ok, _lv, html} = live(conn, "/sites")
text = text(html)
+
assert text =~ "My personal sites"
- assert text =~ "You don't have any sites yet"
- refute text =~ "You currently have no personal sites"
- refute text =~ "Go to your team"
+ assert text =~ "Add your first personal site"
+ refute text =~ "Go to team sites"
end
test "renders team switcher link, if on personal sites with other teams available", %{
@@ -33,8 +33,8 @@ defmodule PlausibleWeb.Live.SitesTest do
assert text =~ "My personal sites"
refute text =~ "You don't have any sites yet"
- assert text =~ "You currently have no personal sites"
- assert text =~ "Go to your team"
+ assert text =~ "Add your first personal site"
+ assert text =~ "Go to team sites"
end
test "renders settings link when current team is set", %{user: user, conn: conn} do