mirror of
https://github.com/plausible/analytics.git
synced 2024-12-24 10:02:10 +03:00
b3ff695797
* Add Heroicons dependency
* Add name_of/1 html helper
Currently with Floki there's no way to query for
`[name=foo[some]]` selector
* Update changelog
* Make goal deletion possible with only goal id
* Remove stale goal controllers
* Improve ComboBox component
- make sure the list options are always of the parent input width
- allow passing a suggestion function instead of a module
* Stale fixup
* Update routes
* Use the new goals route in funnel settings
* Use a function in the funnel combo
* Use function in the props combo
* Remove old goals form
* Implement new goal settings
* Update moduledoc
* Fix revenue switch in dark mode
* Connect live socket on goal settings page
* Fixup
* Use Heroicons.trash icon
* Tweak goals search input
* Remove unused alias
* Fix search/button alignment
* Fix backspace icon alignment
* Delegate :superadmin check to get_for_user/3
I'll do props settings separately, it's work in progress
in a branch on top of this one already. cc @ukutaht
* Rename socket assigns
* Fixup to 5c9f58e
* Fixup
* Render ComboBox suggestions asynchronously
This commit:
- prevents redundant work by checking the socket connection
- allows passing no options to the ComboBox component,
so that when combined with the `async` option, the options
are asynchronously initialized post-render
- allows updating the suggestions asynchronously with the
`async` option set to `true` - helpful in case of DB
queries used for suggestions
* Update tests
* Throttle comboboxes
* Update tests
* Dim the search input
* Use debounce=200 in ComboBox component
* Move creatable option to the top
* Ensure there's always a leading slash for goals
* Test pageview goals with leading / missing
* Make the modal scrollable on small viewports
104 lines
3.3 KiB
Elixir
104 lines
3.3 KiB
Elixir
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
|
|
true = Plausible.Funnels.enabled_for?("user:#{user_id}")
|
|
|
|
site = Sites.get_for_user!(user_id, domain, [:owner, :admin, :superadmin])
|
|
|
|
funnels = Funnels.list(site)
|
|
goal_count = Goals.count(site)
|
|
|
|
{:ok,
|
|
assign(socket,
|
|
site_id: site.id,
|
|
domain: site.domain,
|
|
funnels: funnels,
|
|
goal_count: goal_count,
|
|
add_funnel?: false,
|
|
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"""
|
|
<div id="funnel-settings-main">
|
|
<.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 %>
|
|
<div :if={@goal_count >= Funnel.min_steps()}>
|
|
<.live_component
|
|
module={PlausibleWeb.Live.FunnelSettings.List}
|
|
id="funnels-list"
|
|
funnels={@funnels}
|
|
/>
|
|
<button type="button" class="button mt-6" phx-click="add-funnel">+ Add funnel</button>
|
|
</div>
|
|
|
|
<div :if={@goal_count < Funnel.min_steps()}>
|
|
<PlausibleWeb.Components.Generic.notice class="mt-4" title="Not enough goals">
|
|
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.
|
|
</PlausibleWeb.Components.Generic.notice>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
"""
|
|
end
|
|
|
|
def handle_event("add-funnel", _value, socket) do
|
|
{:noreply, assign(socket, add_funnel?: true)}
|
|
end
|
|
|
|
def handle_event("cancel-add-funnel", _value, socket) do
|
|
{:noreply, assign(socket, add_funnel?: false)}
|
|
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, funnels: Enum.reject(socket.assigns.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, funnels: [funnel | socket.assigns.funnels])}
|
|
end
|
|
|
|
def handle_info(:clear_flash, socket) do
|
|
{:noreply, clear_flash(socket)}
|
|
end
|
|
end
|