Update goal settings design (#5886)
* Update goal settings design - Replace the `Add goal` button in goal settings with a dropdown button to directly select the goal type. This way, a modal opens with the correct form for the selected goal type. The tabs in the modal have been removed. - Add a new `pill` component to show the goal type in the table in a more distinct way. The `settings_badge` component is replaced with the `pill` component. The `pill` component that was used in `plan_box.ex` is renamed to `highlight_pill`. - Replaced `Belongs to funnel` text with a funnel icon in the goal settings list. - Some small tweaks like increasing the search bar width, the padding of the table cells, and adding a header to the goal settings list. * Update tests to use the new dropdown component instead of tabs * Replace custom `pending invitation` pill with new pill component * Temporary: bump prima to exercise prima dropdown LV re-render fix * Temporary: Bump prima again * Revert "Temporary: Bump prima again" This reverts commit024b34a6e9. * Revert "Temporary: bump prima to exercise prima dropdown LV re-render fix" This reverts commita6eabb73d0. * Update prima * Replace `Add goal` button with dropdown button in goal settings empty state * Update test to check both empty and non-empty states of the add goal dropdown * Remove pb-14 from feature gate --------- Co-authored-by: Adam Rutkowski <hq@mtod.org>
This commit is contained in:
parent
f2bc96debe
commit
2c00acc89b
|
|
@ -39,7 +39,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||
]}>
|
||||
{String.capitalize(to_string(@kind))}
|
||||
</h3>
|
||||
<.pill :if={@highlight} text={@highlight} />
|
||||
<.highlight_pill :if={@highlight} text={@highlight} />
|
||||
</div>
|
||||
<div>
|
||||
<div class={@price_container_class}>
|
||||
|
|
@ -95,7 +95,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
|||
"""
|
||||
end
|
||||
|
||||
defp pill(assigns) do
|
||||
defp highlight_pill(assigns) do
|
||||
~H"""
|
||||
<div class="flex items-center justify-between gap-x-4">
|
||||
<p
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ defmodule PlausibleWeb.Components.Generic do
|
|||
current_team={@current_team}
|
||||
site={@site}
|
||||
>
|
||||
<div class="p-6 pb-14">
|
||||
<div class="p-6">
|
||||
{render_slot(@inner_block)}
|
||||
</div>
|
||||
</PlausibleWeb.Components.Billing.feature_gate>
|
||||
|
|
@ -793,7 +793,7 @@ defmodule PlausibleWeb.Components.Generic do
|
|||
<td
|
||||
class={[
|
||||
@height,
|
||||
"text-sm px-6 py-3 first:pl-0 last:pr-0 whitespace-nowrap",
|
||||
"text-sm px-6 py-4 first:pl-0 last:pr-0 whitespace-nowrap",
|
||||
@truncate && "truncate",
|
||||
@max_width,
|
||||
@actions && "flex text-right justify-end",
|
||||
|
|
@ -1027,10 +1027,15 @@ defmodule PlausibleWeb.Components.Generic do
|
|||
|
||||
def filter_bar(assigns) do
|
||||
~H"""
|
||||
<div class="flex items-center justify-between" x-data>
|
||||
<div :if={@filtering_enabled?} class="relative rounded-md flex">
|
||||
<form id="filter-form" phx-change="filter" phx-submit="filter" class="flex items-center">
|
||||
<div class="text-gray-800 inline-flex items-center">
|
||||
<div class="flex items-center justify-between gap-2" x-data>
|
||||
<div :if={@filtering_enabled?} class="relative rounded-md flex flex-grow-1 w-full">
|
||||
<form
|
||||
id="filter-form"
|
||||
phx-change="filter"
|
||||
phx-submit="filter"
|
||||
class="flex items-center w-full"
|
||||
>
|
||||
<div class="text-gray-800 inline-flex items-center w-full">
|
||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
<Heroicons.magnifying_glass class="feather mr-1 dark:text-gray-300" />
|
||||
</div>
|
||||
|
|
@ -1038,7 +1043,7 @@ defmodule PlausibleWeb.Components.Generic do
|
|||
type="text"
|
||||
name="filter-text"
|
||||
id="filter-text"
|
||||
class="w-full max-w-64 pl-8 text-sm dark:bg-gray-750 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block border-gray-300 dark:border-gray-750 rounded-md dark:placeholder:text-gray-400 focus:outline-none focus:ring-3 focus:ring-indigo-500/20 dark:focus:ring-indigo-500/25 focus:border-indigo-500"
|
||||
class="w-full max-w-80 pl-8 text-sm dark:bg-gray-750 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block border-gray-300 dark:border-gray-750 rounded-md dark:placeholder:text-gray-400 focus:outline-none focus:ring-3 focus:ring-indigo-500/20 dark:focus:ring-indigo-500/25 focus:border-indigo-500"
|
||||
placeholder="Press / to search"
|
||||
x-ref="filter_text"
|
||||
phx-debounce={200}
|
||||
|
|
@ -1140,13 +1145,41 @@ defmodule PlausibleWeb.Components.Generic do
|
|||
"""
|
||||
end
|
||||
|
||||
def settings_badge(%{type: :new} = assigns) do
|
||||
attr(:class, :string, default: "")
|
||||
attr(:color, :atom, default: :gray, values: [:gray, :indigo, :yellow, :green])
|
||||
attr(:rest, :global)
|
||||
slot(:inner_block, required: true)
|
||||
|
||||
def pill(assigns) do
|
||||
assigns = assign(assigns, :color_classes, get_pill_color_classes(assigns.color))
|
||||
|
||||
~H"""
|
||||
<span class="inline-block ml-2 bg-indigo-100 text-indigo-600 text-xs font-semibold py-1 px-2 rounded-md">
|
||||
NEW 🔥
|
||||
<span
|
||||
class={[
|
||||
"inline-flex items-center text-xs font-medium py-1 px-2 rounded-md",
|
||||
@color_classes,
|
||||
@class
|
||||
]}
|
||||
{@rest}
|
||||
>
|
||||
{render_slot(@inner_block)}
|
||||
</span>
|
||||
"""
|
||||
end
|
||||
|
||||
def settings_badge(assigns), do: ~H""
|
||||
defp get_pill_color_classes(:gray) do
|
||||
"bg-gray-100 text-gray-800 dark:bg-gray-750 dark:text-gray-200"
|
||||
end
|
||||
|
||||
defp get_pill_color_classes(:indigo) do
|
||||
"bg-indigo-100/60 text-indigo-600 dark:bg-indigo-900/50 dark:text-indigo-300"
|
||||
end
|
||||
|
||||
defp get_pill_color_classes(:yellow) do
|
||||
"bg-yellow-100/80 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300"
|
||||
end
|
||||
|
||||
defp get_pill_color_classes(:green) do
|
||||
"bg-green-100/70 text-green-800 dark:bg-green-900/40 dark:text-green-300"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -140,7 +140,9 @@ defmodule PlausibleWeb.Components.Layout do
|
|||
class="size-5 mr-2"
|
||||
/>
|
||||
{@text}
|
||||
<PlausibleWeb.Components.Generic.settings_badge type={@badge} />
|
||||
<PlausibleWeb.Components.Generic.pill :if={@badge == :new} color={:indigo} class="ml-2">
|
||||
NEW 🔥
|
||||
</PlausibleWeb.Components.Generic.pill>
|
||||
<Heroicons.chevron_down
|
||||
:if={is_nil(@value)}
|
||||
class="h-3 w-3 ml-2 text-gray-400 dark:text-gray-500"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ defmodule PlausibleWeb.Components.PrimaDropdown do
|
|||
<Dropdown.dropdown_item
|
||||
as={@as}
|
||||
disabled={@disabled}
|
||||
class="group/item z-50 flex items-center gap-x-2 min-w-max rounded-md px-4 py-2 text-gray-700 text-sm dark:text-gray-300 data-focus:bg-gray-100 dark:data-focus:bg-gray-700 data-focus:text-gray-900 dark:data-focus:text-gray-100"
|
||||
class="group/item z-50 flex items-center gap-x-2 min-w-max w-full rounded-md pl-3 pr-5 py-2 text-gray-700 text-sm dark:text-gray-300 data-focus:bg-gray-100 dark:data-focus:bg-gray-700 data-focus:text-gray-900 dark:data-focus:text-gray-100"
|
||||
{@rest}
|
||||
>
|
||||
{render_slot(@inner_block)}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ defmodule PlausibleWeb.Live.GoalSettings do
|
|||
domain: domain,
|
||||
displayed_goals: socket.assigns.all_goals,
|
||||
filter_text: "",
|
||||
form_goal: nil
|
||||
form_goal: nil,
|
||||
goal_type: nil
|
||||
)}
|
||||
end
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ defmodule PlausibleWeb.Live.GoalSettings do
|
|||
site_team={@site_team}
|
||||
existing_goals={@all_goals}
|
||||
goal={@form_goal}
|
||||
goal_type={@goal_type}
|
||||
on_save_goal={
|
||||
fn goal, socket ->
|
||||
send(self(), {:goal_added, goal})
|
||||
|
|
@ -137,8 +139,12 @@ defmodule PlausibleWeb.Live.GoalSettings do
|
|||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("add-goal", _, socket) do
|
||||
socket = socket |> assign(form_goal: nil) |> Modal.open("goals-form-modal")
|
||||
def handle_event("add-goal", %{"goal-type" => goal_type}, socket) do
|
||||
socket =
|
||||
socket
|
||||
|> assign(form_goal: nil, goal_type: goal_type)
|
||||
|> Modal.open("goals-form-modal")
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
|
|
@ -181,7 +187,8 @@ defmodule PlausibleWeb.Live.GoalSettings do
|
|||
event_name_options:
|
||||
Enum.reject(socket.assigns.event_name_options, &(&1 == goal.event_name)),
|
||||
displayed_goals: all_goals,
|
||||
form_goal: nil
|
||||
form_goal: nil,
|
||||
goal_type: nil
|
||||
)
|
||||
|> put_live_flash(:success, "Goal saved successfully")
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,15 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
|> Plausible.Goal.changeset()
|
||||
|> to_form()
|
||||
|
||||
selected_tab =
|
||||
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"
|
||||
form_type =
|
||||
if assigns.goal do
|
||||
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"
|
||||
_ -> "custom_events"
|
||||
end
|
||||
else
|
||||
assigns[:goal_type] || "custom_events"
|
||||
end
|
||||
|
||||
socket =
|
||||
|
|
@ -37,14 +41,14 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
current_user: assigns.current_user,
|
||||
site_team: assigns.site_team,
|
||||
domain: assigns.domain,
|
||||
selected_tab: selected_tab,
|
||||
tab_sequence_id: 0,
|
||||
form_type: form_type,
|
||||
site: site,
|
||||
has_access_to_revenue_goals?: has_access_to_revenue_goals?,
|
||||
existing_goals: assigns.existing_goals,
|
||||
on_save_goal: assigns.on_save_goal,
|
||||
on_autoconfigure: assigns.on_autoconfigure,
|
||||
goal: assigns.goal
|
||||
goal: assigns.goal,
|
||||
goal_type: assigns[:goal_type]
|
||||
)
|
||||
|
||||
{:ok, socket}
|
||||
|
|
@ -68,7 +72,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
<.title>Edit goal for {@domain}</.title>
|
||||
|
||||
<.custom_event_fields
|
||||
:if={@selected_tab == "custom_events"}
|
||||
:if={@form_type == "custom_events"}
|
||||
f={f}
|
||||
suffix={@context_unique_id}
|
||||
current_user={@current_user}
|
||||
|
|
@ -80,14 +84,14 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
has_access_to_revenue_goals?={@has_access_to_revenue_goals?}
|
||||
/>
|
||||
<.pageview_fields
|
||||
:if={@selected_tab == "pageviews"}
|
||||
:if={@form_type == "pageviews"}
|
||||
f={f}
|
||||
goal={@goal}
|
||||
suffix={@context_unique_id}
|
||||
site={@site}
|
||||
/>
|
||||
<.scroll_fields
|
||||
:if={@selected_tab == "scroll"}
|
||||
:if={@form_type == "scroll"}
|
||||
f={f}
|
||||
goal={@goal}
|
||||
suffix={@context_unique_id}
|
||||
|
|
@ -103,58 +107,41 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
|
||||
def create_form(assigns) do
|
||||
~H"""
|
||||
<.form
|
||||
:let={f}
|
||||
x-data="{ tabSelectionInProgress: false }"
|
||||
for={@form}
|
||||
phx-submit="save-goal"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.form :let={f} for={@form} phx-submit="save-goal" phx-target={@myself}>
|
||||
<.title>
|
||||
Add goal for {Plausible.Sites.display_name(@site)}
|
||||
</.title>
|
||||
|
||||
<.tabs current_user={@current_user} site={@site} selected_tab={@selected_tab} myself={@myself} />
|
||||
|
||||
<.custom_event_fields
|
||||
:if={@selected_tab == "custom_events"}
|
||||
x-show="!tabSelectionInProgress"
|
||||
:if={@form_type == "custom_events"}
|
||||
f={f}
|
||||
suffix={suffix(@context_unique_id, @tab_sequence_id)}
|
||||
suffix={@context_unique_id}
|
||||
current_user={@current_user}
|
||||
site_team={@site_team}
|
||||
site={@site}
|
||||
existing_goals={@existing_goals}
|
||||
goal_options={@event_name_options}
|
||||
has_access_to_revenue_goals?={@has_access_to_revenue_goals?}
|
||||
x-init="tabSelectionInProgress = false"
|
||||
/>
|
||||
<.pageview_fields
|
||||
:if={@selected_tab == "pageviews"}
|
||||
x-show="!tabSelectionInProgress"
|
||||
:if={@form_type == "pageviews"}
|
||||
f={f}
|
||||
suffix={suffix(@context_unique_id, @tab_sequence_id)}
|
||||
suffix={@context_unique_id}
|
||||
site={@site}
|
||||
x-init="tabSelectionInProgress = false"
|
||||
/>
|
||||
<.scroll_fields
|
||||
:if={@selected_tab == "scroll"}
|
||||
x-show="!tabSelectionInProgress"
|
||||
:if={@form_type == "scroll"}
|
||||
f={f}
|
||||
suffix={suffix(@context_unique_id, @tab_sequence_id)}
|
||||
suffix={@context_unique_id}
|
||||
site={@site}
|
||||
x-init="tabSelectionInProgress = false"
|
||||
/>
|
||||
|
||||
<div x-show="!tabSelectionInProgress">
|
||||
<.button type="submit" class="w-full">
|
||||
Add goal
|
||||
</.button>
|
||||
</div>
|
||||
<.button type="submit" class="w-full">
|
||||
Add goal
|
||||
</.button>
|
||||
|
||||
<button
|
||||
:if={@selected_tab == "custom_events" && @event_name_options_count > 0}
|
||||
x-show="!tabSelectionInProgress"
|
||||
:if={@form_type == "custom_events" && @event_name_options_count > 0}
|
||||
class="mt-4 text-sm hover:underline text-indigo-600 dark:text-indigo-400 text-left"
|
||||
phx-click="autoconfigure"
|
||||
phx-target={@myself}
|
||||
|
|
@ -441,73 +428,6 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
"""
|
||||
end
|
||||
|
||||
def tabs(assigns) do
|
||||
~H"""
|
||||
<div class="text-sm mt-6 font-medium dark:text-gray-100">Goal trigger</div>
|
||||
<div class="my-2 p-1 text-sm w-full flex gap-1 overflow-hidden rounded-lg border border-gray-300 dark:border-gray-700">
|
||||
<.tab
|
||||
id="event-tab"
|
||||
tab_value="custom_events"
|
||||
selected?={@selected_tab == "custom_events"}
|
||||
myself={@myself}
|
||||
>
|
||||
Custom event
|
||||
</.tab>
|
||||
<.tab
|
||||
id="pageview-tab"
|
||||
tab_value="pageviews"
|
||||
selected?={@selected_tab == "pageviews"}
|
||||
myself={@myself}
|
||||
>
|
||||
Pageview
|
||||
</.tab>
|
||||
<.tab
|
||||
id="scroll-tab"
|
||||
tab_value="scroll"
|
||||
selected?={@selected_tab == "scroll"}
|
||||
myself={@myself}
|
||||
>
|
||||
Scroll depth
|
||||
</.tab>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
attr(:id, :string, required: true)
|
||||
attr(:tab_value, :string, required: true)
|
||||
attr(:selected?, :boolean, required: true)
|
||||
attr(:myself, :any, required: true)
|
||||
slot(:inner_block, required: true)
|
||||
|
||||
defp tab(assigns) do
|
||||
~H"""
|
||||
<a
|
||||
class={[
|
||||
"flex-1 text-center py-2 px-3 rounded-md font-medium hover:bg-gray-100 dark:hover:bg-gray-750 transition-colors duration-150",
|
||||
"cursor-pointer",
|
||||
@selected? && "bg-gray-150 dark:bg-gray-700 text-gray-800 dark:text-white",
|
||||
!@selected? && "dark:text-gray-200 text-gray-600 hover:text-gray-800 dark:hover:text-white"
|
||||
]}
|
||||
id={@id}
|
||||
x-on:click={!@selected? && "tabSelectionInProgress = true"}
|
||||
phx-click="switch-tab"
|
||||
phx-value-tab={@tab_value}
|
||||
phx-target={@myself}
|
||||
>
|
||||
{render_slot(@inner_block)}
|
||||
</a>
|
||||
"""
|
||||
end
|
||||
|
||||
def handle_event("switch-tab", %{"tab" => tab}, socket) do
|
||||
socket =
|
||||
socket
|
||||
|> assign(:selected_tab, tab)
|
||||
|> update(:tab_sequence_id, &(&1 + 1))
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("save-goal", %{"goal" => goal_params}, %{assigns: %{goal: nil}} = socket) do
|
||||
case Plausible.Goals.create(socket.assigns.site, goal_params) do
|
||||
{:ok, goal} ->
|
||||
|
|
@ -572,10 +492,6 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
|||
|> Enum.map(fn name -> {name, name} end)
|
||||
end
|
||||
|
||||
defp suffix(context_unique_id, tab_sequence_id) do
|
||||
"#{context_unique_id}-tabseq#{tab_sequence_id}"
|
||||
end
|
||||
|
||||
on_ee do
|
||||
defp currency_option(nil), do: nil
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
|
|||
"""
|
||||
use PlausibleWeb, :live_component
|
||||
alias PlausibleWeb.Live.Components.Modal
|
||||
alias PlausibleWeb.Components.PrimaDropdown
|
||||
|
||||
attr(:goals, :list, required: true)
|
||||
attr(:domain, :string, required: true)
|
||||
|
|
@ -19,25 +20,52 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
|
|||
|> assign(:searching?, String.trim(assigns.filter_text) != "")
|
||||
|
||||
~H"""
|
||||
<div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<%= if @searching? or Enum.count(@goals) > 0 do %>
|
||||
<.filter_bar filter_text={@filter_text} placeholder="Search Goals">
|
||||
<.button
|
||||
id="add-goal-button"
|
||||
phx-click="add-goal"
|
||||
mt?={false}
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
>
|
||||
Add goal
|
||||
</.button>
|
||||
<PrimaDropdown.dropdown id="add-goal-dropdown">
|
||||
<PrimaDropdown.dropdown_trigger as={&button/1} mt?={false}>
|
||||
Add goal <Heroicons.chevron_down mini class="size-4 mt-0.5" />
|
||||
</PrimaDropdown.dropdown_trigger>
|
||||
|
||||
<PrimaDropdown.dropdown_menu>
|
||||
<PrimaDropdown.dropdown_item
|
||||
phx-click="add-goal"
|
||||
phx-value-goal-type="pageviews"
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
>
|
||||
<Heroicons.plus class={PrimaDropdown.dropdown_item_icon_class()} /> Pageview
|
||||
</PrimaDropdown.dropdown_item>
|
||||
<PrimaDropdown.dropdown_item
|
||||
phx-click="add-goal"
|
||||
phx-value-goal-type="custom_events"
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
>
|
||||
<Heroicons.plus class={PrimaDropdown.dropdown_item_icon_class()} /> Custom event
|
||||
</PrimaDropdown.dropdown_item>
|
||||
<PrimaDropdown.dropdown_item
|
||||
phx-click="add-goal"
|
||||
phx-value-goal-type="scroll"
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
>
|
||||
<Heroicons.plus class={PrimaDropdown.dropdown_item_icon_class()} /> Scroll depth
|
||||
</PrimaDropdown.dropdown_item>
|
||||
</PrimaDropdown.dropdown_menu>
|
||||
</PrimaDropdown.dropdown>
|
||||
</.filter_bar>
|
||||
<% end %>
|
||||
|
||||
<%= if Enum.count(@goals) > 0 do %>
|
||||
<.table rows={@goals}>
|
||||
<:thead>
|
||||
<.th>Name</.th>
|
||||
<.th hide_on_mobile>Type</.th>
|
||||
</:thead>
|
||||
<:tbody :let={goal}>
|
||||
<.td max_width="max-w-40" height="h-16">
|
||||
<.td max_width="max-w-64" height="h-16">
|
||||
<%= if not @revenue_goals_enabled? && goal.currency do %>
|
||||
<div class="truncate">{goal}</div>
|
||||
<.tooltip>
|
||||
|
|
@ -52,20 +80,27 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
|
|||
</span>
|
||||
</.tooltip>
|
||||
<% else %>
|
||||
<div class="font-medium text-sm flex items-center gap-1.5">
|
||||
<span class="truncate">{goal}</span>
|
||||
<.tooltip :if={not Enum.empty?(goal.funnels)} centered?={true}>
|
||||
<:tooltip_content>
|
||||
Belongs to funnel
|
||||
</:tooltip_content>
|
||||
<Heroicons.funnel class="size-3.5 stroke-2 flex-shrink-0" />
|
||||
</.tooltip>
|
||||
</div>
|
||||
<div class="truncate">
|
||||
<.goal_description goal={goal} />
|
||||
</div>
|
||||
<div class="truncate">{goal}</div>
|
||||
<% end %>
|
||||
</.td>
|
||||
<.td hide_on_mobile height="h-16">
|
||||
<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-500">
|
||||
<br />Belongs to funnel(s)
|
||||
</span>
|
||||
<.pill :if={goal.page_path && goal.scroll_threshold > -1} color={:green}>Scroll</.pill>
|
||||
<.pill :if={goal.page_path && goal.scroll_threshold == -1} color={:gray}>
|
||||
Pageview
|
||||
</.pill>
|
||||
<.pill :if={goal.event_name && !goal.currency} color={:yellow}>Custom Event</.pill>
|
||||
<.pill :if={goal.currency} color={:indigo}>Revenue Goal ({goal.currency})</.pill>
|
||||
</.td>
|
||||
<.td actions height="h-16">
|
||||
<.edit_button
|
||||
|
|
@ -125,15 +160,38 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
|
|||
Learn more
|
||||
</.styled_link>
|
||||
</p>
|
||||
<.button
|
||||
id="add-goal-button"
|
||||
phx-click="add-goal"
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
class="mt-4"
|
||||
>
|
||||
Add goal
|
||||
</.button>
|
||||
<PrimaDropdown.dropdown id="add-goal-dropdown-empty" class="mt-4">
|
||||
<PrimaDropdown.dropdown_trigger as={&button/1} mt?={false}>
|
||||
Add goal <Heroicons.chevron_down mini class="size-4 mt-0.5" />
|
||||
</PrimaDropdown.dropdown_trigger>
|
||||
|
||||
<PrimaDropdown.dropdown_menu>
|
||||
<PrimaDropdown.dropdown_item
|
||||
phx-click="add-goal"
|
||||
phx-value-goal-type="pageviews"
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
>
|
||||
<Heroicons.plus class={PrimaDropdown.dropdown_item_icon_class()} /> Pageview
|
||||
</PrimaDropdown.dropdown_item>
|
||||
<PrimaDropdown.dropdown_item
|
||||
phx-click="add-goal"
|
||||
phx-value-goal-type="custom_events"
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
>
|
||||
<Heroicons.plus class={PrimaDropdown.dropdown_item_icon_class()} /> Custom event
|
||||
</PrimaDropdown.dropdown_item>
|
||||
<PrimaDropdown.dropdown_item
|
||||
phx-click="add-goal"
|
||||
phx-value-goal-type="scroll"
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("goals-form-modal")}
|
||||
>
|
||||
<Heroicons.plus class={PrimaDropdown.dropdown_item_icon_class()} /> Scroll depth
|
||||
</PrimaDropdown.dropdown_item>
|
||||
</PrimaDropdown.dropdown_menu>
|
||||
</PrimaDropdown.dropdown>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
|||
|
|
@ -98,52 +98,54 @@ defmodule PlausibleWeb.Live.SharedLinkSettings do
|
|||
</.button>
|
||||
</div>
|
||||
<% else %>
|
||||
<.filter_bar filtering_enabled?={false}>
|
||||
<.button
|
||||
id="add-shared-link-button"
|
||||
phx-click="add-shared-link"
|
||||
mt?={false}
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("shared-links-form-modal")}
|
||||
>
|
||||
Add shared link
|
||||
</.button>
|
||||
</.filter_bar>
|
||||
<div class="flex flex-col gap-4">
|
||||
<.filter_bar filtering_enabled?={false}>
|
||||
<.button
|
||||
id="add-shared-link-button"
|
||||
phx-click="add-shared-link"
|
||||
mt?={false}
|
||||
x-data
|
||||
x-on:click={Modal.JS.preopen("shared-links-form-modal")}
|
||||
>
|
||||
Add shared link
|
||||
</.button>
|
||||
</.filter_bar>
|
||||
|
||||
<.table rows={@shared_links} id="shared-links-table">
|
||||
<:thead>
|
||||
<.th hide_on_mobile>Name</.th>
|
||||
<.th>Link</.th>
|
||||
<.th invisible>Actions</.th>
|
||||
</:thead>
|
||||
<:tbody :let={link}>
|
||||
<.td truncate hide_on_mobile>
|
||||
{link.name}
|
||||
<Heroicons.lock_closed :if={link.password_hash} class="feather ml-2 mb-0.5" />
|
||||
<Heroicons.lock_open :if={!link.password_hash} class="feather ml-2 mb-0.5" />
|
||||
</.td>
|
||||
<.td>
|
||||
<.input_with_clipboard
|
||||
name={link.slug}
|
||||
id={link.slug}
|
||||
value={Plausible.Sites.shared_link_url(@site, link)}
|
||||
/>
|
||||
</.td>
|
||||
<.td actions>
|
||||
<.edit_button
|
||||
class="mt-1"
|
||||
phx-click="edit-shared-link"
|
||||
phx-value-slug={link.slug}
|
||||
/>
|
||||
<.delete_button
|
||||
class="mt-1"
|
||||
phx-click="delete-shared-link"
|
||||
phx-value-slug={link.slug}
|
||||
data-confirm="Are you sure you want to delete this shared link? The stats will not be accessible with this link anymore."
|
||||
/>
|
||||
</.td>
|
||||
</:tbody>
|
||||
</.table>
|
||||
<.table rows={@shared_links} id="shared-links-table">
|
||||
<:thead>
|
||||
<.th hide_on_mobile>Name</.th>
|
||||
<.th>Link</.th>
|
||||
<.th invisible>Actions</.th>
|
||||
</:thead>
|
||||
<:tbody :let={link}>
|
||||
<.td truncate hide_on_mobile>
|
||||
{link.name}
|
||||
<Heroicons.lock_closed :if={link.password_hash} class="feather ml-2 mb-0.5" />
|
||||
<Heroicons.lock_open :if={!link.password_hash} class="feather ml-2 mb-0.5" />
|
||||
</.td>
|
||||
<.td>
|
||||
<.input_with_clipboard
|
||||
name={link.slug}
|
||||
id={link.slug}
|
||||
value={Plausible.Sites.shared_link_url(@site, link)}
|
||||
/>
|
||||
</.td>
|
||||
<.td actions>
|
||||
<.edit_button
|
||||
class="mt-1"
|
||||
phx-click="edit-shared-link"
|
||||
phx-value-slug={link.slug}
|
||||
/>
|
||||
<.delete_button
|
||||
class="mt-1"
|
||||
phx-click="delete-shared-link"
|
||||
phx-value-slug={link.slug}
|
||||
data-confirm="Are you sure you want to delete this shared link? The stats will not be accessible with this link anymore."
|
||||
/>
|
||||
</.td>
|
||||
</:tbody>
|
||||
</.table>
|
||||
</div>
|
||||
<% end %>
|
||||
</.tile>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -508,9 +508,9 @@ defmodule PlausibleWeb.Live.Sites do
|
|||
{@site.domain}
|
||||
</h3>
|
||||
</div>
|
||||
<span class="inline-flex items-center -my-1 px-2 py-1 rounded-sm bg-green-100 text-green-800 text-xs font-medium leading-normal dark:bg-green-900/40 dark:text-green-400">
|
||||
<.pill color={:green}>
|
||||
Pending invitation
|
||||
</span>
|
||||
</.pill>
|
||||
</div>
|
||||
<.site_stats hourly_stats={@hourly_stats} />
|
||||
</div>
|
||||
|
|
|
|||
4
mix.lock
4
mix.lock
|
|
@ -131,11 +131,11 @@
|
|||
"phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"},
|
||||
"php_serializer": {:hex, :php_serializer, "2.0.0", "b43f31aca22ed7321f32da2b94fe2ddf9b6739a965cb51541969119e572e821d", [:mix], [], "hexpm", "61e402e99d9062c0225a3f4fcf7e43b4cba1b8654944c0e7c139c3ca9de481da"},
|
||||
"plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.7.4", "729c752d17cf364e2b8da5bdb34fb5804f56251e88bb602aff48ae0bd8673d11", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9b85632bd7012615bae0a5d70084deb1b25d2bcbb32cab82d1e9a1e023168aa3"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.7.5", "261f21b67aea8162239b2d6d3b4c31efde4daa22a20d80b19c2c0f21b34b270e", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "20884bf58a90ff5a5663420f5d2c368e9e15ed1ad5e911daf0916ea3c57f77ac"},
|
||||
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
|
||||
"polymorphic_embed": {:hex, :polymorphic_embed, "5.0.3", "37444e0af941026a2c29b0539b6471bdd6737a6492a19264bf2bb0118e3ac242", [:mix], [{:attrs, "~> 0.6", [hex: :attrs, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "2fed44f57abf0a0fc7642e0eb0807a55b65de1562712cc0620772cbbb80e49c1"},
|
||||
"postgrex": {:hex, :postgrex, "0.19.3", "a0bda6e3bc75ec07fca5b0a89bffd242ca209a4822a9533e7d3e84ee80707e19", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d31c28053655b78f47f948c85bb1cf86a9c1f8ead346ba1aa0d0df017fa05b61"},
|
||||
"prima": {:hex, :prima, "0.1.8", "1f57fb7000046bb463b2a31200b138dd10c86fd78a289f1e947a970f740b68e0", [:mix], [{:esbuild, "~> 0.7", [hex: :esbuild, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "b559ee8213a8302fd40520cc55b0fcafbc884d471d198b262dd1e0a10170de17"},
|
||||
"prima": {:hex, :prima, "0.1.9", "34868e3570cf2c4fac42d6254e33678e9d75a8fe3d3253a38ee437f6481a2896", [:mix], [{:esbuild, "~> 0.7", [hex: :esbuild, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "7f24efb617dd94da867bf2d362eeab846897270eff989aeaa261f04590feae3f"},
|
||||
"prom_ex": {:hex, :prom_ex, "1.11.0", "1f6d67f2dead92224cb4f59beb3e4d319257c5728d9638b4a5e8ceb51a4f9c7e", [:mix], [{:absinthe, ">= 1.7.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.1.0", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.11.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.10.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.4", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:peep, "~> 3.0", [hex: :peep, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.16.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.6.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "76b074bc3730f0802978a7eb5c7091a65473eaaf07e99ec9e933138dcc327805"},
|
||||
"public_suffix": {:git, "https://github.com/axelson/publicsuffix-elixir", "fa40c243d4b5d8598b90cff268bc4e33f3bb63f1", []},
|
||||
"ranch": {:hex, :ranch, "1.8.1", "208169e65292ac5d333d6cdbad49388c1ae198136e4697ae2f474697140f201c", [:make, :rebar3], [], "hexpm", "aed58910f4e21deea992a67bf51632b6d60114895eb03bb392bb733064594dd0"},
|
||||
|
|
|
|||
|
|
@ -12,32 +12,43 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
describe "integration - live rendering" do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "tabs switching", %{conn: conn, site: site} do
|
||||
test "form renders with custom events when selected from dropdown", %{conn: conn, site: site} do
|
||||
setup_goals(site)
|
||||
lv = get_liveview(conn, site)
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("custom_events")
|
||||
|
||||
html = lv |> render()
|
||||
html = render(lv)
|
||||
|
||||
assert html =~ "Add goal for #{site.domain}"
|
||||
assert element_exists?(html, ~s/a#pageview-tab/)
|
||||
assert element_exists?(html, ~s/a#event-tab/)
|
||||
refute element_exists?(html, "#pageviews-form")
|
||||
refute element_exists?(html, "#scroll-form")
|
||||
assert element_exists?(html, "#custom-events-form")
|
||||
|
||||
pageview_tab = lv |> element(~s/a#pageview-tab/) |> render_click()
|
||||
assert pageview_tab =~ "Page path"
|
||||
|
||||
event_tab = lv |> element(~s/a#event-tab/) |> render_click()
|
||||
assert event_tab =~ "Event name"
|
||||
assert html =~ "Event name"
|
||||
end
|
||||
|
||||
test "can navigate to scroll tab if scroll_depth feature visible for site/user",
|
||||
%{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site)
|
||||
lv |> element(~s/a#scroll-tab/) |> render_click()
|
||||
test "form renders with pageview when selected from dropdown", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("pageviews")
|
||||
|
||||
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
|
||||
|
||||
assert html =~ "Add goal for #{site.domain}"
|
||||
refute element_exists?(html, "#custom-events-form")
|
||||
refute element_exists?(html, "#scroll-form")
|
||||
assert element_exists?(html, "#pageviews-form")
|
||||
assert html =~ "Page path"
|
||||
end
|
||||
|
||||
test "form renders with scroll when selected from dropdown", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("scroll")
|
||||
|
||||
html = render(lv)
|
||||
|
||||
assert html =~ "Add goal for #{site.domain}"
|
||||
refute element_exists?(html, "#custom-events-form")
|
||||
refute element_exists?(html, "#pageviews-form")
|
||||
assert element_exists?(html, "#scroll-form")
|
||||
assert html =~ "Scroll percentage threshold"
|
||||
assert html =~ "Page path"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -45,8 +56,9 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
@tag :ee_only
|
||||
test "renders form fields per tab, with currency", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site)
|
||||
test "renders form fields for custom events with currency", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("custom_events")
|
||||
|
||||
html = render(lv)
|
||||
|
||||
refute element_exists?(html, "#pageviews-form")
|
||||
|
|
@ -55,30 +67,35 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
|
||||
assert input_names ==
|
||||
[
|
||||
"display-event_name_input_modalseq0-tabseq0",
|
||||
"display-event_name_input_modalseq0",
|
||||
"goal[event_name]",
|
||||
"goal[display_name]",
|
||||
"display-currency_input_modalseq0-tabseq0",
|
||||
"display-currency_input_modalseq0",
|
||||
"goal[currency]"
|
||||
]
|
||||
end
|
||||
|
||||
lv |> element(~s/a#pageview-tab/) |> render_click()
|
||||
html = lv |> render()
|
||||
@tag :ee_only
|
||||
test "renders form fields for pageview", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("pageviews")
|
||||
|
||||
html = render(lv)
|
||||
|
||||
refute element_exists?(html, "#custom-events-form")
|
||||
|
||||
input_names = html |> find("#pageviews-form input") |> Enum.map(&name_of/1)
|
||||
|
||||
assert input_names == [
|
||||
"display-page_path_input_modalseq0-tabseq1",
|
||||
"display-page_path_input_modalseq0",
|
||||
"goal[page_path]",
|
||||
"goal[display_name]"
|
||||
]
|
||||
end
|
||||
|
||||
@tag :ce_build_only
|
||||
test "renders form fields per tab (no currency)", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site)
|
||||
test "renders form fields for custom events (no currency)", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("custom_events")
|
||||
|
||||
html = render(lv)
|
||||
|
||||
refute element_exists?(html, "#pageviews-form")
|
||||
|
|
@ -87,39 +104,34 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
|
||||
assert input_names ==
|
||||
[
|
||||
"display-event_name_input_modalseq0-tabseq0",
|
||||
"display-event_name_input_modalseq0",
|
||||
"goal[event_name]",
|
||||
"goal[display_name]"
|
||||
]
|
||||
|
||||
lv |> element(~s/a#pageview-tab/) |> render_click()
|
||||
html = lv |> render()
|
||||
|
||||
refute element_exists?(html, "#custom-events-form")
|
||||
|
||||
input_names = html |> find("#pageviews-form input") |> Enum.map(&name_of/1)
|
||||
|
||||
assert input_names == [
|
||||
"display-page_path_input_modalseq0-tabseq1",
|
||||
"goal[page_path]",
|
||||
"goal[display_name]"
|
||||
]
|
||||
end
|
||||
|
||||
test "renders error on empty submission", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site)
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("custom_events")
|
||||
|
||||
lv |> element("#goals-form-modalseq0 form") |> render_submit()
|
||||
html = render(lv)
|
||||
assert html =~ "this field is required and cannot be blank"
|
||||
end
|
||||
|
||||
pageview_tab = lv |> element(~s/a#pageview-tab/) |> render_click()
|
||||
assert pageview_tab =~ "this field is required and must start with a /"
|
||||
test "renders error on empty pageview submission", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("pageviews")
|
||||
|
||||
lv |> element("#goals-form-modalseq0 form") |> render_submit()
|
||||
html = render(lv)
|
||||
assert html =~ "this field is required and must start with a /"
|
||||
end
|
||||
|
||||
test "creates a custom event", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site)
|
||||
refute render(lv) =~ "SampleCustomEvent"
|
||||
|
||||
lv = open_modal_with_goal_type(lv, "custom_events")
|
||||
|
||||
lv
|
||||
|> element("#goals-form-modalseq0 form")
|
||||
|> render_submit(%{goal: %{event_name: "SampleCustomEvent"}})
|
||||
|
|
@ -319,15 +331,15 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
|
||||
@tag :ee_only
|
||||
test "currency combo works", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site)
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("custom_events")
|
||||
|
||||
type_into_combo(lv, "currency_input_modalseq0-tabseq0", "Polish")
|
||||
type_into_combo(lv, "currency_input_modalseq0", "Polish")
|
||||
html = render(lv)
|
||||
|
||||
assert element_exists?(html, ~s/a[phx-value-display-value="PLN - Polish Zloty"]/)
|
||||
refute element_exists?(html, ~s/a[phx-value-display-value="EUR - Euro"]/)
|
||||
|
||||
type_into_combo(lv, "currency_input_modalseq0-tabseq0", "Euro")
|
||||
type_into_combo(lv, "currency_input_modalseq0", "Euro")
|
||||
html = render(lv)
|
||||
|
||||
refute element_exists?(html, ~s/a[phx-value-display-value="PLN - Polish Zloty"]/)
|
||||
|
|
@ -335,10 +347,9 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
end
|
||||
|
||||
test "pageview combo works", %{conn: conn, site: site} do
|
||||
lv = get_liveview(conn, site)
|
||||
lv |> element(~s/a#pageview-tab/) |> render_click()
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("pageviews")
|
||||
|
||||
html = type_into_combo(lv, "page_path_input_modalseq0-tabseq1", "/hello")
|
||||
html = type_into_combo(lv, "page_path_input_modalseq0", "/hello")
|
||||
|
||||
assert html =~ "Create "/hello""
|
||||
end
|
||||
|
|
@ -349,17 +360,16 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
build(:pageview, pathname: "/go/home")
|
||||
])
|
||||
|
||||
lv = get_liveview(conn, site)
|
||||
lv |> element(~s/a#pageview-tab/) |> render_click()
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("pageviews")
|
||||
|
||||
type_into_combo(lv, "page_path_input_modalseq0-tabseq1", "/go/to/p")
|
||||
type_into_combo(lv, "page_path_input_modalseq0", "/go/to/p")
|
||||
|
||||
html = render(lv)
|
||||
assert html =~ "Create "/go/to/p""
|
||||
assert html =~ "/go/to/page/1"
|
||||
refute html =~ "/go/home"
|
||||
|
||||
type_into_combo(lv, "page_path_input_modalseq0-tabseq1", "/go/h")
|
||||
type_into_combo(lv, "page_path_input_modalseq0", "/go/h")
|
||||
html = render(lv)
|
||||
assert html =~ "/go/home"
|
||||
refute html =~ "/go/to/page/1"
|
||||
|
|
@ -373,17 +383,16 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
build(:imported_pages, page: "/go/home", pageviews: 1)
|
||||
])
|
||||
|
||||
lv = get_liveview(conn, site)
|
||||
lv |> element(~s/a#pageview-tab/) |> render_click()
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("pageviews")
|
||||
|
||||
type_into_combo(lv, "page_path_input_modalseq0-tabseq1", "/go/to/p")
|
||||
type_into_combo(lv, "page_path_input_modalseq0", "/go/to/p")
|
||||
|
||||
html = render(lv)
|
||||
assert html =~ "Create "/go/to/p""
|
||||
assert html =~ "/go/to/page/1"
|
||||
refute html =~ "/go/home"
|
||||
|
||||
type_into_combo(lv, "page_path_input_modalseq0-tabseq1", "/go/h")
|
||||
type_into_combo(lv, "page_path_input_modalseq0", "/go/h")
|
||||
html = render(lv)
|
||||
assert html =~ "/go/home"
|
||||
refute html =~ "/go/to/page/1"
|
||||
|
|
@ -396,9 +405,9 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
build(:event, name: "EventThree")
|
||||
])
|
||||
|
||||
lv = get_liveview(conn, site)
|
||||
lv = get_liveview(conn, site) |> open_modal_with_goal_type("custom_events")
|
||||
|
||||
type_into_combo(lv, "event_name_input_modalseq0-tabseq0", "One")
|
||||
type_into_combo(lv, "event_name_input_modalseq0", "One")
|
||||
html = render(lv)
|
||||
|
||||
assert text_of_element(html, "#goals-form-modalseq0") =~ "EventOne"
|
||||
|
|
@ -451,4 +460,12 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
|
|||
|
||||
lv
|
||||
end
|
||||
|
||||
defp open_modal_with_goal_type(lv, goal_type) do
|
||||
lv
|
||||
|> element(~s/[phx-click="add-goal"][phx-value-goal-type="#{goal_type}"]/)
|
||||
|> render_click()
|
||||
|
||||
lv
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -89,10 +89,33 @@ defmodule PlausibleWeb.Live.GoalSettingsTest do
|
|||
refute resp =~ "Create your first goal"
|
||||
end
|
||||
|
||||
test "add goal button is rendered", %{conn: conn, site: site} do
|
||||
test "add goal dropdown is rendered in empty state", %{conn: conn, site: site} do
|
||||
conn = get(conn, "/#{site.domain}/settings/goals")
|
||||
resp = html_response(conn, 200)
|
||||
assert element_exists?(resp, ~s/button#add-goal-button[phx-click="add-goal"]/)
|
||||
assert element_exists?(resp, ~s/[id="add-goal-dropdown-empty"]/)
|
||||
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/[phx-click="add-goal"][phx-value-goal-type="custom_events"]/
|
||||
)
|
||||
|
||||
assert element_exists?(resp, ~s/[phx-click="add-goal"][phx-value-goal-type="pageviews"]/)
|
||||
assert element_exists?(resp, ~s/[phx-click="add-goal"][phx-value-goal-type="scroll"]/)
|
||||
end
|
||||
|
||||
test "add goal dropdown is rendered in non-empty state", %{conn: conn, site: site} do
|
||||
{:ok, _goals} = setup_goals(site)
|
||||
conn = get(conn, "/#{site.domain}/settings/goals")
|
||||
resp = html_response(conn, 200)
|
||||
assert element_exists?(resp, ~s/[id="add-goal-dropdown"]/)
|
||||
|
||||
assert element_exists?(
|
||||
resp,
|
||||
~s/[phx-click="add-goal"][phx-value-goal-type="custom_events"]/
|
||||
)
|
||||
|
||||
assert element_exists?(resp, ~s/[phx-click="add-goal"][phx-value-goal-type="pageviews"]/)
|
||||
assert element_exists?(resp, ~s/[phx-click="add-goal"][phx-value-goal-type="scroll"]/)
|
||||
end
|
||||
|
||||
test "search goals input is rendered", %{conn: conn, site: site} do
|
||||
|
|
|
|||
Loading…
Reference in New Issue