defmodule PlausibleWeb.Live.FunnelSettings do
@moduledoc """
LiveView allowing listing, creating and deleting funnels.
"""
use Phoenix.LiveView
use Phoenix.HTML
use Plausible.Funnel
alias Plausible.{Sites, Goals, Funnels}
def mount(
_params,
%{"site_id" => site_id, "domain" => domain, "current_user_id" => user_id},
socket
) do
socket =
socket
|> assign_new(:site, fn ->
Sites.get_for_user!(user_id, domain, [:owner, :admin, :super_admin])
end)
|> assign_new(:all_funnels, fn %{site: %{id: ^site_id} = site} ->
Funnels.list(site)
end)
|> assign_new(:goal_count, fn %{site: site} ->
Goals.count(site)
end)
{:ok,
assign(socket,
domain: domain,
displayed_funnels: socket.assigns.all_funnels,
add_funnel?: false,
filter_text: "",
current_user_id: user_id
)}
end
# Flash sharing with live views within dead views can be done via re-rendering the flash partial.
# Normally, we'd have to use live_patch which we can't do with views unmounted at the router it seems.
def render(assigns) do
~H"""
<.live_component id="embedded_liveview_flash" module={PlausibleWeb.Live.Flash} flash={@flash} />
<%= if @add_funnel? do %>
<%= live_render(
@socket,
PlausibleWeb.Live.FunnelSettings.Form,
id: "funnels-form",
session: %{
"current_user_id" => @current_user_id,
"domain" => @domain
}
) %>
<% else %>
= Funnel.min_steps()}>
<.live_component
module={PlausibleWeb.Live.FunnelSettings.List}
id="funnels-list"
funnels={@displayed_funnels}
filter_text={@filter_text}
/>
You need to define at least two goals to create a funnel. Go ahead and <%= link(
"add goals",
to: PlausibleWeb.Router.Helpers.site_path(@socket, :settings_goals, @domain),
class: "text-indigo-500 w-full text-center"
) %> to proceed.
<% end %>
"""
end
def handle_event("reset-filter-text", _params, socket) do
{:noreply, assign(socket, filter_text: "", displayed_funnels: socket.assigns.all_funnels)}
end
def handle_event("filter", %{"filter-text" => filter_text}, socket) do
new_list =
PlausibleWeb.Live.Components.ComboBox.StaticSearch.suggest(
filter_text,
socket.assigns.all_funnels,
to_string: & &1.name
)
{:noreply, assign(socket, displayed_funnels: new_list, filter_text: filter_text)}
end
def handle_event("add-funnel", _value, socket) do
{:noreply, assign(socket, add_funnel?: true)}
end
def handle_event("delete-funnel", %{"funnel-id" => id}, socket) do
site =
Sites.get_for_user!(socket.assigns.current_user_id, socket.assigns.domain, [:owner, :admin])
id = String.to_integer(id)
:ok = Funnels.delete(site, id)
socket = put_flash(socket, :success, "Funnel deleted successfully")
Process.send_after(self(), :clear_flash, 5000)
{:noreply,
assign(socket,
all_funnels: Enum.reject(socket.assigns.all_funnels, &(&1.id == id)),
displayed_funnels: Enum.reject(socket.assigns.displayed_funnels, &(&1.id == id))
)}
end
def handle_info({:funnel_saved, funnel}, socket) do
socket = put_flash(socket, :success, "Funnel saved successfully")
Process.send_after(self(), :clear_flash, 5000)
{:noreply,
assign(socket,
add_funnel?: false,
all_funnels: [funnel | socket.assigns.all_funnels],
displayed_funnels: [funnel | socket.assigns.displayed_funnels]
)}
end
def handle_info(:cancel_add_funnel, socket) do
{:noreply, assign(socket, add_funnel?: false)}
end
def handle_info(:clear_flash, socket) do
{:noreply, clear_flash(socket)}
end
end