diff --git a/lib/plausible_web/components/generic.ex b/lib/plausible_web/components/generic.ex index cda27ed0692c..89e1272e0b24 100644 --- a/lib/plausible_web/components/generic.ex +++ b/lib/plausible_web/components/generic.ex @@ -485,8 +485,9 @@ defmodule PlausibleWeb.Components.Generic do attr :feature_toggle?, :boolean, default: false attr :current_role, :atom, default: nil attr :current_team, :any, default: nil + attr :current_user, :any, default: nil attr :site, :any - attr :conn, :any + attr :conn, :any, default: nil attr :show_content?, :boolean, default: true def tile(assigns) do @@ -506,6 +507,7 @@ defmodule PlausibleWeb.Components.Generic do feature_mod={@feature_mod} site={@site} conn={@conn} + current_user={@current_user} />
diff --git a/lib/plausible_web/components/site/feature.ex b/lib/plausible_web/components/site/feature.ex index 2bc74a55b5f9..7ef068672611 100644 --- a/lib/plausible_web/components/site/feature.ex +++ b/lib/plausible_web/components/site/feature.ex @@ -7,11 +7,12 @@ defmodule PlausibleWeb.Components.Site.Feature do attr(:site, Plausible.Site, required: true) attr(:feature_mod, :atom, required: true, values: Plausible.Billing.Feature.list()) - attr(:conn, Plug.Conn, required: true) + attr(:conn, :any, default: nil) + attr(:current_user, :any, default: nil) attr(:class, :any, default: nil) slot(:inner_block) - def toggle(assigns) do + def toggle(%{conn: %Plug.Conn{}} = assigns) do assigns = assigns |> assign(:current_setting, assigns.feature_mod.enabled?(assigns.site)) @@ -37,7 +38,22 @@ defmodule PlausibleWeb.Components.Site.Feature do """ end - def target(site, setting, conn, set_to) when is_boolean(set_to) do + def toggle(assigns) do + ~H""" + <.live_component + module={PlausibleWeb.Components.Site.Feature.ToggleLive} + id={"feature-toggle-#{@site.id}-#{@feature_mod}"} + site={@site} + feature_mod={@feature_mod} + current_user={@current_user} + class={@class} + > + {render_slot(@inner_block)} + + """ + end + + defp target(site, setting, conn, set_to) when is_boolean(set_to) do r = conn.request_path Routes.site_path(conn, :update_feature_visibility, site.domain, setting, r: r, set: set_to) end diff --git a/lib/plausible_web/components/site/toggle_live.ex b/lib/plausible_web/components/site/toggle_live.ex new file mode 100644 index 000000000000..0ab51752af44 --- /dev/null +++ b/lib/plausible_web/components/site/toggle_live.ex @@ -0,0 +1,96 @@ +defmodule PlausibleWeb.Components.Site.Feature.ToggleLive do + @moduledoc """ + LiveComponent for rendering a user-facing feature toggle in LiveView contexts. + Instead of using form submission, this component messages itself to handle toggles. + """ + use PlausibleWeb, :live_component + + def update(assigns, socket) do + site = Plausible.Repo.preload(assigns.site, :team) + current_setting = assigns.feature_mod.enabled?(site) + disabled? = assigns.feature_mod.check_availability(site.team) !== :ok + + {:ok, + socket + |> assign(assigns) + |> assign(:site, site) + |> assign(:current_setting, current_setting) + |> assign(:disabled?, disabled?)} + end + + def render(assigns) do + ~H""" +
+
+
+ + + + Show in dashboard + +
+
+ +
+ {render_slot(@inner_block)} +
+
+ """ + end + + def handle_event("toggle", _params, socket) do + site = socket.assigns.site + feature_mod = socket.assigns.feature_mod + current_user = socket.assigns.current_user + + case feature_mod.toggle(site, current_user) do + {:ok, updated_site} -> + new_setting = Map.fetch!(updated_site, feature_mod.toggle_field()) + + message = + if new_setting do + "#{feature_mod.display_name()} are now visible again on your dashboard" + else + "#{feature_mod.display_name()} are now hidden from your dashboard" + end + + {:noreply, + socket + |> assign(:site, updated_site) + |> assign(:current_setting, feature_mod.enabled?(updated_site)) + |> put_flash(:success, message)} + + {:error, _} -> + {:noreply, + socket + |> put_flash( + :error, + "Something went wrong. Failed to toggle #{feature_mod.display_name()} on your dashboard." + )} + end + end +end diff --git a/lib/plausible_web/controllers/site_controller.ex b/lib/plausible_web/controllers/site_controller.ex index f0e16a687fbf..a036dbf8a2f6 100644 --- a/lib/plausible_web/controllers/site_controller.ex +++ b/lib/plausible_web/controllers/site_controller.ex @@ -163,19 +163,9 @@ defmodule PlausibleWeb.SiteController do def settings_visibility(conn, _params) do site = conn.assigns[:site] - has_shared_links? = - Repo.exists?( - from(l in Plausible.Site.SharedLink, - where: - l.site_id == ^site.id and - l.name not in ^Plausible.Sites.shared_link_special_names() - ) - ) - conn |> render("settings_visibility.html", site: site, - has_shared_links?: has_shared_links?, dogfood_page_path: "/:dashboard/settings/visibility", connect_live_socket: true, layout: {PlausibleWeb.LayoutView, "site_settings.html"} diff --git a/lib/plausible_web/live/shared_link_settings.ex b/lib/plausible_web/live/shared_link_settings.ex index fcbcbd78066c..51eadd5df635 100644 --- a/lib/plausible_web/live/shared_link_settings.ex +++ b/lib/plausible_web/live/shared_link_settings.ex @@ -18,6 +18,10 @@ defmodule PlausibleWeb.Live.SharedLinkSettings do current_user |> Plausible.Sites.get_for_user!(domain, roles: [:owner, :admin, :editor, :super_admin]) end) + |> assign_new(:site_role, fn %{site: site, current_user: current_user} -> + {:ok, {_, site_role}} = Plausible.Teams.Memberships.site_role(site, current_user) + site_role + end) |> assign_new(:shared_links, fn %{site: site} -> Plausible.Repo.all( from(l in Plausible.Site.SharedLink, @@ -41,96 +45,111 @@ defmodule PlausibleWeb.Live.SharedLinkSettings do """ end diff --git a/lib/plausible_web/templates/site/settings_visibility.html.heex b/lib/plausible_web/templates/site/settings_visibility.html.heex index da4bf02c8963..4ff9a25b6d29 100644 --- a/lib/plausible_web/templates/site/settings_visibility.html.heex +++ b/lib/plausible_web/templates/site/settings_visibility.html.heex @@ -27,27 +27,11 @@ - <.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 :if={@has_shared_links?}> - Share your stats privately with anyone. Links are unique, secure, and can be password-protected. - - -
- {live_render(@conn, PlausibleWeb.Live.SharedLinkSettings, - session: %{"site_id" => @site.id, "domain" => @site.domain} - )} -
- +
+ {live_render(@conn, PlausibleWeb.Live.SharedLinkSettings, + session: %{"site_id" => @site.id, "domain" => @site.domain} + )} +
<.tile docs="embed-dashboard"