analytics/lib/plausible_web/live/goal_settings/list.ex

139 lines
5.2 KiB
Elixir
Raw Normal View History

Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
defmodule PlausibleWeb.Live.GoalSettings.List do
@moduledoc """
Phoenix LiveComponent module that renders a list of goals
"""
use Phoenix.LiveComponent, global_prefixes: ~w(x-)
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
use Phoenix.HTML
alias PlausibleWeb.Live.Components.Modal
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
attr(:goals, :list, required: true)
attr(:domain, :string, required: true)
attr(:filter_text, :string)
attr(:site, Plausible.Site, required: true)
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
def render(assigns) do
revenue_goals_enabled? = Plausible.Billing.Feature.RevenueGoals.enabled?(assigns.site)
assigns = assign(assigns, :revenue_goals_enabled?, revenue_goals_enabled?)
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
~H"""
<div>
<div class="border-t border-gray-200 pt-4 sm:flex sm:items-center sm:justify-between">
<form id="filter-form" phx-change="filter">
<div class="text-gray-800 text-sm inline-flex items-center">
<div class="relative rounded-md shadow-sm flex">
<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>
<input
type="text"
name="filter-text"
id="filter-text"
class="pl-8 shadow-sm dark:bg-gray-900 dark:text-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 dark:border-gray-500 rounded-md dark:bg-gray-800"
placeholder="Search Goals"
value={@filter_text}
/>
</div>
<Heroicons.backspace
:if={String.trim(@filter_text) != ""}
class="feather ml-2 cursor-pointer hover:text-red-500 dark:text-gray-300 dark:hover:text-red-500"
phx-click="reset-filter-text"
id="reset-filter"
/>
</div>
</form>
<div class="mt-4 flex sm:ml-4 sm:mt-0">
<PlausibleWeb.Components.Generic.button
id="add-goal-button"
x-data
x-on:click={Modal.JS.open("goals-form-modal")}
>
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
+ Add Goal
</PlausibleWeb.Components.Generic.button>
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
</div>
</div>
<%= if Enum.count(@goals) > 0 do %>
<div class="mt-12">
<%= for goal <- @goals do %>
<div class="border-b border-gray-300 dark:border-gray-500 py-3 flex justify-between">
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 w-3/4">
<div class="flex">
<span class="truncate">
<%= if not @revenue_goals_enabled? && goal.currency do %>
<div class="text-gray-600 flex items-center">
<Heroicons.lock_closed class="w-4 h-4 mr-1 inline" />
<span><%= goal %></span>
</div>
<% else %>
<%= goal %>
<% end %>
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
<span class="text-sm text-gray-400 block mt-1 font-normal">
<span :if={goal.page_path}>Pageview</span>
<span :if={goal.event_name && !goal.currency}>Custom Event</span>
<span :if={goal.currency && @revenue_goals_enabled?}>
Plugins API: 2nd pass with Goals resource + SharedLinks schema changes (#3396) * Remove "Context" namespace level * Change Goal string representation * Alias Schemas in Plugin API Test Case template * Update schema & tests for SharedLink resource * Update Goals interface - make it possible to create revenue goals - extract "for site" query to a standalone function * Fixup typespecs * Alias Errors module in OpenAPI controllers * Add missing goals test * Implement Goals Plugins API resource * Add extra test to confirm changeset error propagation * Mute credo * Fix typos * Handle changeset traversal in `Errors` * Use upserts in `Goals.find_or_create` * Extract touch_site! to Site.Cache, address credo, improve code docs * Apply formatting * Remove unused inner join * Update test/plausible_web/plugins/api/controllers/goals_test.exs Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com> * Update test/plausible_web/plugins/api/controllers/goals_test.exs Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com> * Update test/plausible_web/plugins/api/controllers/goals_test.exs Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com> * Update test/plausible_web/plugins/api/controllers/goals_test.exs Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com> * Update test/plausible_web/plugins/api/controllers/goals_test.exs Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com> * Update error message on revenue goal currency clash * Remove unused code --------- Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
2023-10-05 12:54:18 +03:00
Revenue Goal
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
</span>
<span :if={goal.currency && not @revenue_goals_enabled?} class="text-red-600">
Unlock Revenue Goals by upgrading to a business plan
</span>
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
<span :if={not Enum.empty?(goal.funnels)}> - belongs to funnel(s)</span>
</span>
</span>
</div>
</span>
<button
id={"delete-goal-#{goal.id}"}
phx-click="delete-goal"
phx-value-goal-id={goal.id}
phx-value-goal-name={goal.event_name}
Improve goal settings UX (#3293) * 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
2023-09-04 14:44:22 +03:00
class="text-sm text-red-600"
data-confirm={delete_confirmation_text(goal)}
>
<Heroicons.trash class="feather feather-sm" />
</button>
</div>
<% end %>
</div>
<% else %>
<p class="text-sm text-gray-800 dark:text-gray-200 mt-12 mb-8 text-center">
<span :if={String.trim(@filter_text) != ""}>
No goals found for this site. Please refine or
<a
class="text-indigo-500 cursor-pointer underline"
phx-click="reset-filter-text"
id="reset-filter-hint"
>
reset your search.
</a>
</span>
<span :if={String.trim(@filter_text) == "" && Enum.empty?(@goals)}>
No goals configured for this site.
</span>
</p>
<% end %>
</div>
"""
end
defp delete_confirmation_text(goal) do
if Enum.empty?(goal.funnels) do
"""
Are you sure you want to remove the following goal:
#{goal}
This will just affect the UI, all of your analytics data will stay intact.
"""
else
"""
The goal:
#{goal}
is part of some funnel(s). If you are going to delete it, the associated funnels will be either reduced or deleted completely. Are you sure you want to remove the goal?
"""
end
end
end