analytics / lib /plausible /stats /dashboard /query_parser.ex
Leon4gr45's picture
Upload folder using huggingface_hub (part 2)
8da2481 verified
Raw
History Blame Contribute Delete
4.26 kB
defmodule Plausible.Stats.Dashboard.QueryParser do
@moduledoc """
Parses a dashboard query string into `%ParsedQueryParams{}`. Note that
`metrics` and `dimensions` do not exist at this step yet, and are expected
to be filled in by each specific report.
"""
alias Plausible.Stats.{ParsedQueryParams, QueryInclude, ApiQueryParser, QueryError}
@valid_comparison_shorthands %{
"previous_period" => :previous_period,
"year_over_year" => :year_over_year
}
@valid_comparison_shorthand_keys Map.keys(@valid_comparison_shorthands)
def parse(params, opts \\ []) do
with {:ok, input_date_range} <- parse_input_date_range(params),
{:ok, relative_date} <- parse_relative_date(params),
{:ok, dimensions} <- ApiQueryParser.parse_dimensions(params["dimensions"]),
{:ok, filters} <- ApiQueryParser.parse_filters(params["filters"]),
{:ok, metrics} <- parse_metrics(params),
{:ok, order_by} <- ApiQueryParser.parse_order_by(params["order_by"]),
{:ok, pagination} <- ApiQueryParser.parse_pagination(params["pagination"]),
{:ok, include} <- parse_include(params) do
{:ok,
ParsedQueryParams.new!(%{
input_date_range: input_date_range,
relative_date: relative_date,
dimensions: dimensions,
filters: filters,
metrics: metrics,
order_by: order_by,
pagination: pagination,
include: include,
skip_goal_existence_check: true,
now: Keyword.get(opts, :now)
})}
end
end
defp parse_input_date_range(%{"date_range" => date_range}) do
case date_range do
"realtime" -> {:ok, :realtime}
"realtime_30m" -> {:ok, :realtime_30m}
date_range -> ApiQueryParser.parse_input_date_range(date_range)
end
end
defp parse_input_date_range(_) do
{:error,
%QueryError{code: :invalid_date_range, message: "Required 'date_range' parameter missing"}}
end
defp parse_relative_date(%{"relative_date" => date}) when is_binary(date) do
case Date.from_iso8601(date) do
{:ok, date} ->
{:ok, date}
_ ->
{:error,
%QueryError{code: :invalid_relative_date, message: "Failed to convert '#{date}' to date"}}
end
end
defp parse_relative_date(_), do: {:ok, nil}
defp parse_metrics(%{"metrics" => [_ | _] = metrics}) do
ApiQueryParser.parse_metrics(metrics)
end
defp parse_metrics(_),
do:
{:error,
%QueryError{
code: :invalid_metrics,
message: "Expected at least one valid metric in 'metrics'"
}}
defp parse_include(params) do
with {:ok, compare} <- parse_include_compare(params["include"]) do
{:ok,
%QueryInclude{
imports: params["include"]["imports"] == true,
imports_meta: params["include"]["imports_meta"] == true,
compare: compare,
compare_match_day_of_week: params["include"]["compare_match_day_of_week"] == true,
time_labels: params["include"]["time_labels"] == true,
partial_time_labels: params["include"]["partial_time_labels"] == true,
present_index: params["include"]["present_index"] == true,
empty_metrics: params["include"]["empty_metrics"] == true,
trim_relative_date_range: true,
drop_unavailable_time_on_page: true,
drop_unavailable_revenue_metrics: true
}}
end
end
defp parse_include_compare(%{"compare" => compare})
when compare in @valid_comparison_shorthand_keys do
{:ok, @valid_comparison_shorthands[compare]}
end
defp parse_include_compare(%{"compare" => [from, to] = compare})
when is_binary(from) and is_binary(to) do
case ApiQueryParser.parse_date_strings(from, to) do
{:ok, compare} ->
{:ok, compare}
{:error, _} ->
{:error,
%QueryError{
code: :invalid_include,
message: "Invalid include.compare '#{inspect(compare)}'"
}}
end
end
defp parse_include_compare(%{"compare" => compare}) when not is_nil(compare) do
{:error,
%QueryError{code: :invalid_include, message: "Invalid include.compare '#{inspect(compare)}'"}}
end
defp parse_include_compare(_) do
{:ok, nil}
end
end