diff --git a/lib/plausible_web/components/layouts.ex b/lib/plausible_web/components/layouts.ex index 5a2604508ec0..1d916e5e977a 100644 --- a/lib/plausible_web/components/layouts.ex +++ b/lib/plausible_web/components/layouts.ex @@ -15,6 +15,7 @@ defmodule PlausibleWeb.Layouts do attr :footer?, :boolean, default: true attr :global_notices?, :boolean, default: true attr :trial_badge?, :boolean, default: true + attr :team_switcher?, :boolean, default: true attr :embedded?, :boolean, default: false attr :load_dashboard_js?, :boolean, default: false attr :flash, :map, default: %{} @@ -38,6 +39,7 @@ defmodule PlausibleWeb.Layouts do current_team={@current_team} current_team_role={@current_team_role} trial_badge?={@trial_badge?} + team_switcher?={@team_switcher?} teams={@teams} my_team={@my_team} /> @@ -152,6 +154,7 @@ defmodule PlausibleWeb.Layouts do footer?={false} global_notices?={false} trial_badge?={false} + team_switcher?={false} current_user={@current_user} flash={@flash} > diff --git a/lib/plausible_web/components/layouts/header.html.heex b/lib/plausible_web/components/layouts/header.html.heex index c463509794f2..a3673f6ca57b 100644 --- a/lib/plausible_web/components/layouts/header.html.heex +++ b/lib/plausible_web/components/layouts/header.html.heex @@ -63,6 +63,8 @@

-
- <.dropdown_item - class="flex" - href={~p"/team/setup"} - > - - Create a team - - - <.dropdown_divider /> -
-
<.dropdown_item class="flex" diff --git a/lib/plausible_web/views/layout_view.ex b/lib/plausible_web/views/layout_view.ex index 210e886c4fe0..5f79de807fe5 100644 --- a/lib/plausible_web/views/layout_view.ex +++ b/lib/plausible_web/views/layout_view.ex @@ -164,73 +164,62 @@ defmodule PlausibleWeb.LayoutView do end end + attr :current_user, :any, required: true attr :teams, :list, required: true attr :my_team, :any, default: nil attr :current_team, :any, default: nil def team_switcher(assigns) do - teams = assigns[:teams] + personal_team = + assigns.my_team || %Teams.Team{identifier: "none", name: Teams.default_name()} - if teams && teams != [] do - current_team = assigns[:current_team] - my_team = assigns[:my_team] - current_included? = current_team && Enum.any?(teams, &(&1.id == current_team.id)) - current_is_my? = current_team && my_team && current_team.id == my_team.id + current_team = assigns.current_team || personal_team - teams = - if current_team && !current_included? && !current_is_my? do - [current_team | teams] - else - teams - end - - teams = - if my_team do - teams ++ [my_team] - else - teams ++ [%Teams.Team{identifier: "none", name: Teams.default_name()}] - end + other_teams = + [personal_team | Enum.sort_by(assigns.teams, &String.downcase(&1.name))] + |> Enum.reject(&(&1.id == current_team.id)) - selected_id = current_team && current_team.id - {pinned_team, other_teams} = Enum.split_with(teams, &(&1.id == selected_id)) + assigns = + assigns + |> assign(:current_team, current_team) + |> assign(:personal_team, personal_team) + |> assign(:other_teams, other_teams) - assigns = - assigns - |> assign(:pinned_team, List.first(pinned_team)) - |> assign(:other_teams, other_teams) - - ~H""" - <.dropdown_item> -
Teams
- + ~H""" + <.dropdown_item> +
Teams
+ + <.dropdown_item href={~p"/sites?#{[__team: @current_team.identifier]}"}> +
+

+ {Teams.name(@current_team)} +

+ +
+ +
<.dropdown_item - :if={@pinned_team} - href={~p"/sites?#{[__team: @pinned_team.identifier]}"} + :for={team <- @other_teams} + href={~p"/sites?#{[__team: team.identifier]}"} > -
-

- {Teams.name(@pinned_team)} -

- -
- -
- <.dropdown_item - :for={team <- @other_teams} - href={~p"/sites?#{[__team: team.identifier]}"} +

-

- {Teams.name(team)} -

- + {Teams.name(team)} +

+ +
+ <.dropdown_item + :if={Plausible.Users.type(@current_user) == :standard} + href={~p"/team/setup?#{[__team: @personal_team.identifier]}"} + > +
+ Create new team +
- """ - else - ~H"" - end + + """ end def trial_notification(team) do diff --git a/test/plausible_web/controllers/settings_controller_test.exs b/test/plausible_web/controllers/settings_controller_test.exs index a2583dafae82..3d9a297c3bdf 100644 --- a/test/plausible_web/controllers/settings_controller_test.exs +++ b/test/plausible_web/controllers/settings_controller_test.exs @@ -1561,7 +1561,7 @@ defmodule PlausibleWeb.SettingsControllerTest do %{conn: conn} do conn = get(conn, ~p"/settings/preferences") html = html_response(conn, 200) - refute html =~ "Team" + refute html =~ "Team settings" expected_account_menu = if(ee?(), @@ -1700,11 +1700,21 @@ defmodule PlausibleWeb.SettingsControllerTest do end test "does not render team settings, when team not set up", %{conn: conn, user: user} do - {:ok, team} = Plausible.Teams.get_or_create(user) + {:ok, _team} = Plausible.Teams.get_or_create(user) conn = get(conn, ~p"/settings/preferences") html = html_response(conn, 200) - refute html =~ ~r/Team.*#{Regex.escape(team.name)}/s - refute html =~ team.name + refute html =~ "Team settings" + + expected_account_menu = + if(ee?(), + do: [:preferences, :security, :subscription, :api_keys, :danger_zone], + else: [:preferences, :security, :api_keys, :danger_zone] + ) + + html + |> LazyHTML.from_document() + |> assert_sidebar_menu(expected_account_menu) + |> assert_mobile_menu(expected_account_menu) end test "GET /settings/team/general", %{conn: conn, user: user} do @@ -2236,22 +2246,48 @@ defmodule PlausibleWeb.SettingsControllerTest do describe "account dropdown menu (_header.html)" do setup [:create_user, :log_in] - test "renders the 'Create a team' option", %{conn: conn, user: user} do + test "renders the 'Create new team' option", %{conn: conn, user: user} do subscribe_to_growth_plan(user) conn = get(conn, ~p"/settings/preferences") html = html_response(conn, 200) - assert text_of_element(html, ~s/[data-test="create-a-team-cta"]/) == "Create a team" + assert text_of_element(html, ~s/[data-test="create-a-team-cta"]/) == "Create new team" end - test "does not render the 'Create a team' option if a team is already set up", %{ - conn: conn, - user: user - } do + test "renders the 'Create new team' option for the personal team when a team is already set up", + %{conn: conn, user: user} do {:ok, team} = Plausible.Teams.get_or_create(user) Plausible.Teams.complete_setup(team) - conn = get(conn, ~p"/settings/preferences") + conn = get(set_current_team(conn, team), ~p"/settings/preferences") + html = html_response(conn, 200) + + assert html |> find(~s|a[href^="/team/setup"]|) |> LazyHTML.attribute("href") == [ + "/team/setup?__team=none" + ] + end + + test "renders the 'Create new team' option for the existing personal team when another team is selected", + %{conn: conn, user: user} do + site = new_site(owner: user) + other_team = insert(:team, name: "Zeta", identifier: Ecto.UUID.generate()) + add_member(other_team, user: user, role: :viewer) + conn = get(set_current_team(conn, other_team), ~p"/settings/preferences") html = html_response(conn, 200) - refute element_exists?(html, ~s/[data-test="create-a-team-cta"]/) + + assert html |> find(~s|a[href^="/team/setup"]|) |> LazyHTML.attribute("href") == [ + "/team/setup?__team=#{site.team.identifier}" + ] + end + end + + on_ee do + describe "account dropdown menu (_header.html) - SSO user" do + setup [:create_user, :create_site, :create_team, :setup_sso, :provision_sso_user, :log_in] + + test "does not render the 'Create new team' option", %{conn: conn} do + conn = get(conn, ~p"/settings/preferences") + html = html_response(conn, 200) + refute element_exists?(html, ~s/[data-test="create-a-team-cta"]/) + end end end diff --git a/test/plausible_web/live/sites_test.exs b/test/plausible_web/live/sites_test.exs index 259c5877bbf0..90432976a82f 100644 --- a/test/plausible_web/live/sites_test.exs +++ b/test/plausible_web/live/sites_test.exs @@ -40,6 +40,38 @@ defmodule PlausibleWeb.Live.SitesTest do ) end + test "lists personal sites in team switcher when the user has no other teams", %{ + conn: conn, + user: user + } do + new_site(owner: user) + + {:ok, _lv, html} = live(conn, "/sites") + + assert text_of_element(html, ~s|a[href^="/sites?__team="]|) == "My personal sites" + end + + test "lists current team first, personal sites second, then other teams by name", %{ + conn: conn, + user: user + } do + [zeta, beta, alpha] = + for name <- ["Zeta", "Beta", "Alpha"] do + team = insert(:team, name: name, identifier: Ecto.UUID.generate()) + add_member(team, user: user, role: :viewer) + team + end + + {:ok, _lv, html} = live(set_current_team(conn, zeta), "/sites") + + assert html |> find(~s|a[href^="/sites?__team="]|) |> LazyHTML.attribute("href") == [ + "/sites?__team=#{zeta.identifier}", + "/sites?__team=none", + "/sites?__team=#{alpha.identifier}", + "/sites?__team=#{beta.identifier}" + ] + end + test "renders settings link when current team is set", %{user: user, conn: conn} do {:ok, _lv, html} = live(conn, "/sites") diff --git a/test/plausible_web/live/team_setup_test.exs b/test/plausible_web/live/team_setup_test.exs index 989832899721..c103b3af7c5c 100644 --- a/test/plausible_web/live/team_setup_test.exs +++ b/test/plausible_web/live/team_setup_test.exs @@ -44,6 +44,12 @@ defmodule PlausibleWeb.Live.TeamSetupTest do "Set up team" end + test "does not render the team switcher", %{conn: conn, site: site} do + {:ok, _lv, html} = live(conn, onboarding_url(site.domain)) + + refute html =~ "Create new team" + end + test "suggests a team name based on the site domain", %{conn: conn, user: user} do site = new_site(owner: user, domain: "shop.my-company.co.uk")