Skip to content
141 changes: 126 additions & 15 deletions lib/plausible_web/live/goal_settings/form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|> to_form()

selected_tab =
if assigns.goal && assigns.goal.page_path do
"pageviews"
else
"custom_events"
case assigns.goal do
%{page_path: p, scroll_threshold: s} when not is_nil(p) and s > -1 -> "scroll"
%{page_path: p} when not is_nil(p) -> "pageviews"
_goal_or_nil -> "custom_events"
end

socket =
Expand Down Expand Up @@ -84,7 +84,13 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
f={f}
goal={@goal}
suffix={@context_unique_id}
current_user={@current_user}
site={@site}
/>
<.scroll_fields
:if={@selected_tab == "scroll"}
f={f}
goal={@goal}
suffix={@context_unique_id}
site={@site}
/>

Expand All @@ -108,7 +114,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do

<.title>Add Goal for {@domain}</.title>

<.tabs selected_tab={@selected_tab} myself={@myself} />
<.tabs current_user={@current_user} site={@site} selected_tab={@selected_tab} myself={@myself} />

<.custom_event_fields
:if={@selected_tab == "custom_events"}
Expand All @@ -128,7 +134,14 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
x-show="!tabSelectionInProgress"
f={f}
suffix={suffix(@context_unique_id, @tab_sequence_id)}
current_user={@current_user}
site={@site}
x-init="tabSelectionInProgress = false"
/>
<.scroll_fields
:if={@selected_tab == "scroll"}
x-show="!tabSelectionInProgress"
f={f}
suffix={suffix(@context_unique_id, @tab_sequence_id)}
site={@site}
x-init="tabSelectionInProgress = false"
/>
Expand Down Expand Up @@ -158,7 +171,6 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
end

attr(:f, Phoenix.HTML.Form)
attr(:current_user, Plausible.Auth.User)
attr(:site, Plausible.Site)
attr(:suffix, :string)
attr(:goal, Plausible.Goal, default: nil)
Expand Down Expand Up @@ -196,16 +208,91 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
x-data="{ firstFocus: true }"
x-on:focus="if (firstFocus) { $el.select(); firstFocus = false; }"
/>
</div>
"""
end

attr(:f, Phoenix.HTML.Form)
attr(:site, Plausible.Site)
attr(:suffix, :string)
attr(:goal, Plausible.Goal, default: nil)
attr(:rest, :global)

def scroll_fields(assigns) do
js =
if is_nil(assigns.goal) do
"""
{
scrollThreshold: '90',
pagePath: '',
displayName: '',
updateDisplayName() {
if (this.scrollThreshold && this.pagePath) {
this.displayName = `Scroll ${this.scrollThreshold}% on ${this.pagePath}`
}
}
}
"""
else
"""
{
scrollThreshold: '#{assigns.goal.scroll_threshold}',
pagePath: '#{assigns.goal.page_path}',
displayName: '#{assigns.goal.display_name}',
updateDisplayName() {}
}
"""
end

assigns = assign(assigns, :js, js)

~H"""
<div id="scroll-form" class="py-2" x-data={@js} {@rest}>
<.label for={"scroll_threshold_input_#{@suffix}"}>
Scroll Percentage Threshold (1-100)
</.label>

<.input
:if={Plausible.Stats.ScrollDepth.feature_visible?(@site, @current_user)}
label="Scroll Depth Threshold (optional)"
id={"scroll_threshold_input_#{@suffix}"}
required
field={@f[:scroll_threshold]}
type="number"
value={if @goal && @goal.scroll_threshold > -1, do: @goal.scroll_threshold, else: nil}
min="0"
min="1"
max="100"
step="1"
x-model="scrollThreshold"
x-on:change="updateDisplayName"
/>

<.label for={"scroll_page_path_input_#{@suffix}"} class="mt-3">
Page Path
</.label>

<.live_component
id={"scroll_page_path_input_#{@suffix}"}
submit_name="goal[page_path]"
class={[
"py-2"
]}
module={ComboBox}
suggest_fun={fn input, _options -> suggest_page_paths(input, @site) end}
selected={if @goal && @goal.page_path, do: @goal.page_path}
creatable
x-on-selection-change="pagePath = $event.detail.value.displayValue; updateDisplayName()"
/>

<.error :for={msg <- Enum.map(@f[:page_path].errors, &translate_error/1)}>
{msg}
</.error>

<.input
label="Display Name"
id="scroll_display_name_input"
field={@f[:display_name]}
type="text"
x-model="displayName"
x-data="{ firstFocus: true }"
x-on:focus="if (firstFocus) { $el.select(); firstFocus = false; }"
/>
</div>
"""
Expand Down Expand Up @@ -372,9 +459,14 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
def tabs(assigns) do
~H"""
<div class="text-sm mt-6 font-medium dark:text-gray-100">Goal Trigger</div>
<div class="my-2 text-sm w-full flex rounded border border-gray-300 dark:border-gray-500">
<div class="my-2 text-sm w-full flex rounded border border-gray-300 dark:border-gray-500 overflow-hidden">
<.custom_events_tab selected?={@selected_tab == "custom_events"} myself={@myself} />
<.pageviews_tab selected?={@selected_tab == "pageviews"} myself={@myself} />
<.scroll_tab
:if={Plausible.Stats.ScrollDepth.feature_visible?(@site, @current_user)}
selected?={@selected_tab == "scroll"}
myself={@myself}
/>
</div>
"""
end
Expand All @@ -383,7 +475,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
~H"""
<a
class={[
"w-1/2 text-center py-2.5 border-r dark:border-gray-500",
"flex-1 text-center py-2.5 border-r dark:border-gray-500",
"cursor-pointer",
@selected? && "shadow-inner font-medium bg-indigo-600 text-white",
!@selected? && "dark:text-gray-100 text-gray-800"
Expand All @@ -403,7 +495,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
~H"""
<a
class={[
"w-1/2 text-center py-2.5 cursor-pointer",
"flex-1 text-center py-2.5 cursor-pointer",
@selected? && "shadow-inner font-medium bg-indigo-600 text-white",
!@selected? && "dark:text-gray-100 text-gray-800"
]}
Expand All @@ -418,6 +510,25 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
"""
end

def scroll_tab(assigns) do
~H"""
<a
class={[
"flex-1 text-center py-2.5 cursor-pointer border-l dark:border-gray-500",
@selected? && "shadow-inner font-medium bg-indigo-600 text-white",
!@selected? && "dark:text-gray-100 text-gray-800"
]}
id="scroll-tab"
x-on:click={!@selected? && "tabSelectionInProgress = true"}
phx-click="switch-tab"
phx-value-tab="scroll"
phx-target={@myself}
>
Scroll Depth
</a>
"""
end

def handle_event("switch-tab", %{"tab" => tab}, socket) do
socket =
socket
Expand Down
13 changes: 7 additions & 6 deletions lib/plausible_web/live/goal_settings/list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
</div>
</.td>
<.td hide_on_mobile height="h-16">
<span :if={goal.page_path}>Pageview</span><span :if={goal.event_name && !goal.currency}>Custom Event</span><span :if={
goal.currency
}>Revenue Goal (<%= goal.currency %>)</span><span
:if={not Enum.empty?(goal.funnels)}
class="text-gray-400 dark:text-gray-600"
><br />Belongs to funnel(s)</span>
<span :if={goal.page_path && goal.scroll_threshold > -1}>Scroll</span>
<span :if={goal.page_path && goal.scroll_threshold == -1}>Pageview</span>
<span :if={goal.event_name && !goal.currency}>Custom Event</span>
<span :if={goal.currency}>Revenue Goal ({goal.currency})</span>
<span :if={not Enum.empty?(goal.funnels)} class="text-gray-400 dark:text-gray-600">
<br />Belongs to funnel(s)
</span>
</.td>
<.td actions height="h-16">
<.edit_button
Expand Down
39 changes: 19 additions & 20 deletions test/plausible_web/live/goal_settings/form_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
event_tab = lv |> element(~s/a#event-tab/) |> render_click()
assert event_tab =~ "Event Name"
end

test "can navigate to scroll tab if scroll_depth feature visible for site/user",
%{conn: conn, site: site} do
Plausible.Sites.set_scroll_depth_visible_at(site)

lv = get_liveview(conn, site)
lv |> element(~s/a#scroll-tab/) |> render_click()
html = render(lv)
input_names = html |> find("#scroll-form input") |> Enum.map(&name_of/1)
assert "goal[scroll_threshold]" in input_names
assert "goal[page_path]" in input_names
assert "goal[display_name]" in input_names
end

test "does not render scroll tab if scroll_depth feature not visible for site/user",
%{conn: conn, site: site} do
html = get_liveview(conn, site) |> render()
refute element_exists?(html, ~s/a#scroll-tab/)
end
end

describe "Goal submission" do
Expand Down Expand Up @@ -88,26 +107,6 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
]
end

test "renders scroll_threshold input in pageview goal form if scroll_depth feature visible for site/user",
%{conn: conn, site: site} do
Plausible.Sites.set_scroll_depth_visible_at(site)

lv = get_liveview(conn, site)
lv |> element(~s/a#pageview-tab/) |> render_click()
html = render(lv)
input_names = html |> find("#pageviews-form input") |> Enum.map(&name_of/1)
assert "goal[scroll_threshold]" in input_names
end

test "does not render scroll_threshold input in pageview goal form if scroll_depth feature not visible for site/user",
%{conn: conn, site: site} do
lv = get_liveview(conn, site)
lv |> element(~s/a#pageview-tab/) |> render_click()
html = render(lv)
input_names = html |> find("#pageviews-form input") |> Enum.map(&name_of/1)
refute "goal[scroll_threshold]" in input_names
end

test "renders error on empty submission", %{conn: conn, site: site} do
lv = get_liveview(conn, site)
lv |> element("#goals-form-modalseq0 form") |> render_submit()
Expand Down
Loading