@@ -683,9 +743,9 @@ defmodule PlausibleWeb.Components.Generic do
if String.contains?(classes, "text-sm") or
String.contains?(classes, "text-xs") do
- ["w-3 h-3"]
+ ["size-3"]
else
- ["w-4 h-4"]
+ ["size-4"]
end
end
@@ -791,15 +851,19 @@ defmodule PlausibleWeb.Components.Generic do
~H"""
diff --git a/lib/plausible_web/controllers/api/internal/segments_controller.ex b/lib/plausible_web/controllers/api/internal/segments_controller.ex
index c7962ba6b8d0..21d873a66a91 100644
--- a/lib/plausible_web/controllers/api/internal/segments_controller.ex
+++ b/lib/plausible_web/controllers/api/internal/segments_controller.ex
@@ -100,6 +100,33 @@ defmodule PlausibleWeb.Api.Internal.SegmentsController do
def delete(%Plug.Conn{} = conn, _params), do: invalid_request(conn)
+ def get_related_shared_links(
+ %Plug.Conn{
+ assigns: %{
+ site: site,
+ current_user: %{id: _user_id},
+ site_role: site_role
+ }
+ } =
+ conn,
+ %{} = params
+ ) do
+ segment_id = normalize_segment_id_param(params["segment_id"])
+
+ case Segments.get_related_shared_links(site, site_role, segment_id) do
+ {:error, :not_enough_permissions} ->
+ H.not_enough_permissions(conn, "Not enough permissions to get related shared links")
+
+ {:error, :segment_not_found} ->
+ segment_not_found(conn, params["segment_id"])
+
+ {:ok, shared_links} ->
+ json(conn, shared_links |> Enum.map(& &1.name))
+ end
+ end
+
+ def get_related_shared_links(%Plug.Conn{} = conn, _params), do: invalid_request(conn)
+
@spec normalize_segment_id_param(any()) :: nil | pos_integer()
defp normalize_segment_id_param(input) do
case Integer.parse(input) do
diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex
index 318690d22da3..ed3b7f930fe6 100644
--- a/lib/plausible_web/controllers/api/stats_controller.ex
+++ b/lib/plausible_web/controllers/api/stats_controller.ex
@@ -14,6 +14,7 @@ defmodule PlausibleWeb.Api.StatsController do
@not_set "(not set)"
plug(:date_validation_plug)
+ plug(:validate_required_filters_plug when action not in [:current_visitors])
@doc """
Returns a time-series based on given parameters.
@@ -1615,6 +1616,43 @@ defmodule PlausibleWeb.Api.StatsController do
end
end
+ defp validate_required_filters_plug(
+ %Plug.Conn{assigns: %{shared_link: %Plausible.Site.SharedLink{segment_id: segment_id}}} =
+ conn,
+ _opts
+ )
+ when is_integer(segment_id) do
+ case ensure_expected_segment_filter_present(conn.params, segment_id) do
+ :ok ->
+ conn
+
+ :error ->
+ bad_request(
+ conn,
+ "The first filter must be for the segment with id #{segment_id}"
+ )
+ end
+ end
+
+ defp validate_required_filters_plug(conn, _opts), do: conn
+
+ defp ensure_expected_segment_filter_present(
+ %{"filters" => filters} = _params,
+ expected_segment_id
+ ) do
+ case JSON.decode!(filters) do
+ [["is", "segment", [segment_id]] | _other_filters] when segment_id == expected_segment_id ->
+ :ok
+
+ _ ->
+ :error
+ end
+ end
+
+ defp ensure_expected_segment_filter_present(_params, _expected_segment_id) do
+ :error
+ end
+
defp parse_date_params(params) do
params
|> Map.take(["from", "to", "date"])
diff --git a/lib/plausible_web/controllers/stats_controller.ex b/lib/plausible_web/controllers/stats_controller.ex
index 94f0c9a2e4c8..a69c15d3f1e3 100644
--- a/lib/plausible_web/controllers/stats_controller.ex
+++ b/lib/plausible_web/controllers/stats_controller.ex
@@ -101,6 +101,7 @@ defmodule PlausibleWeb.StatsController do
consolidated_view?: consolidated_view?,
consolidated_view_available?: consolidated_view_available?,
team_identifier: team_identifier,
+ limited_to_segment_id: nil,
connect_live_socket: PlausibleWeb.Live.Dashboard.enabled?(site)
)
@@ -405,12 +406,34 @@ defmodule PlausibleWeb.StatsController do
not Teams.locked?(shared_link.site.team) ->
current_user = conn.assigns[:current_user]
site_role = get_fallback_site_role(conn)
- shared_link = Plausible.Repo.preload(shared_link, site: :owners)
+ shared_link = Plausible.Repo.preload(shared_link, :segment, site: [:owners])
stats_start_date = Plausible.Sites.stats_start_date(shared_link.site)
flags = get_flags(current_user, shared_link.site)
- {:ok, segments} = Plausible.Segments.get_all_for_site(shared_link.site, site_role)
+ limited_to_segment_id =
+ if Plausible.Site.SharedLink.limited_to_segment?(shared_link) do
+ shared_link.segment.id
+ else
+ nil
+ end
+
+ segments =
+ if is_nil(limited_to_segment_id) do
+ {:ok, segments} = Plausible.Segments.get_all_for_site(shared_link.site, site_role)
+ segments
+ else
+ shared_link.segment
+ |> Map.take([
+ :id,
+ :name,
+ :type,
+ :inserted_at,
+ :updated_at,
+ :segment_data
+ ])
+ |> List.wrap()
+ end
embedded? = conn.params["embed"] == "true"
@@ -444,7 +467,8 @@ defmodule PlausibleWeb.StatsController do
# no shared links for consolidated views
consolidated_view?: false,
consolidated_view_available?: false,
- team_identifier: team_identifier
+ team_identifier: team_identifier,
+ limited_to_segment_id: limited_to_segment_id
)
end
end
diff --git a/lib/plausible_web/live/components/form.ex b/lib/plausible_web/live/components/form.ex
index 04d463ac22bb..0a637312d0e0 100644
--- a/lib/plausible_web/live/components/form.ex
+++ b/lib/plausible_web/live/components/form.ex
@@ -74,8 +74,14 @@ defmodule PlausibleWeb.Live.Components.Form do
def input(%{type: "select"} = assigns) do
~H"""
-
- <.label for={@id} class={if @help_text, do: "mb-0.5", else: "mb-1.5"}>{@label}
+
+ <.label
+ :if={@label != nil and @label != ""}
+ for={@id}
+ class={if @help_text, do: "mb-0.5", else: "mb-1.5"}
+ >
+ {@label}
+
{@help_text}
@@ -138,7 +144,7 @@ defmodule PlausibleWeb.Live.Components.Form do
{@help_text}
{render_slot(@help_content)}
@@ -150,7 +156,7 @@ defmodule PlausibleWeb.Live.Components.Form do
def input(%{type: "textarea"} = assigns) do
~H"""
-
+
<.label class="mb-1.5" for={@id}>{@label}
|