Skip to content

Commit 1ab9e59

Browse files
committed
remove main_graph from Api.StatsController
1 parent 3dcfad6 commit 1ab9e59

1 file changed

Lines changed: 0 additions & 283 deletions

File tree

lib/plausible_web/controllers/api/stats_controller.ex

Lines changed: 0 additions & 283 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ defmodule PlausibleWeb.Api.StatsController do
1010
Query,
1111
Comparisons,
1212
Filters,
13-
Time,
1413
TableDecider,
1514
TimeOnPage,
1615
Dashboard,
@@ -48,173 +47,6 @@ defmodule PlausibleWeb.Api.StatsController do
4847
end
4948
end
5049

51-
@doc """
52-
Returns a time-series based on given parameters.
53-
54-
## Parameters
55-
56-
This API accepts the following parameters:
57-
58-
* `period` - x-axis of the graph, e.g. `12mo`, `day`, `custom`.
59-
60-
* `metric` - y-axis of the graph, e.g. `visits`, `visitors`, `pageviews`.
61-
See the Stats API ["Metrics"](https://plausible.io/docs/stats-api#metrics)
62-
section for more details. Defaults to `visitors`.
63-
64-
* `interval` - granularity of the time-series data. You can think of it as
65-
a `GROUP BY` clause. Possible values are `minute`, `hour`, `date`, `week`,
66-
and `month`. The default depends on the `period` parameter. Check
67-
`Plausible.Query.from/2` for each default.
68-
69-
* `filters` - optional filters to drill down data. See the Stats API
70-
["Filtering"](https://plausible.io/docs/stats-api#filtering) section for
71-
more details.
72-
73-
* `with_imported` - boolean indicating whether to include Google Analytics
74-
imported data or not. Defaults to `false`.
75-
76-
Full example:
77-
```elixir
78-
%{
79-
"from" => "2021-09-06",
80-
"interval" => "month",
81-
"metric" => "visitors",
82-
"period" => "custom",
83-
"to" => "2021-12-13"
84-
}
85-
```
86-
87-
## Response
88-
89-
Returns a map with the following keys:
90-
91-
* `plot` - list of values for the requested metric representing the y-axis
92-
of the graph.
93-
94-
* `labels` - list of date times representing the x-axis of the graph.
95-
96-
* `present_index` - index of the element representing the current date in
97-
`labels` and `plot` lists.
98-
99-
* `interval` - the interval used for querying.
100-
101-
* `includes_imported` - boolean indicating whether imported data
102-
was queried or not.
103-
104-
* `full_intervals` - map of dates indicating whether the interval has been
105-
cut off by the requested date range or not. For example, if looking at a
106-
month week-by-week, some weeks may be cut off by the month boundaries.
107-
It's useful to adjust the graph display slightly in case the interval is
108-
not 'full' so that the user understands why the numbers might be lower for
109-
those partial periods.
110-
111-
Full example:
112-
```elixir
113-
%{
114-
"full_intervals" => %{
115-
"2021-09-01" => false,
116-
"2021-10-01" => true,
117-
"2021-11-01" => true,
118-
"2021-12-01" => false
119-
},
120-
"interval" => "month",
121-
"labels" => ["2021-09-01", "2021-10-01", "2021-11-01", "2021-12-01"],
122-
"plot" => [0, 0, 0, 0],
123-
"present_index" => nil,
124-
"includes_imported" => false
125-
}
126-
```
127-
128-
"""
129-
def main_graph(conn, params) do
130-
site = conn.assigns[:site]
131-
now = conn.private[:now]
132-
133-
with {:ok, dates} <- parse_date_params(params),
134-
:ok <- validate_interval(params),
135-
:ok <- validate_interval_granularity(site, params, dates),
136-
params <- realtime_period_to_30m(params),
137-
query = Query.from(site, params, debug_metadata: debug_metadata(conn), now: now),
138-
query <- Query.set_include(query, :trim_relative_date_range, true),
139-
{:ok, metric} <- parse_and_validate_graph_metric(params, query) do
140-
{timeseries_result, comparison_result, _meta} = Stats.timeseries(site, query, [metric])
141-
142-
labels = label_timeseries(timeseries_result, comparison_result)
143-
present_index = present_index_for(site, query, labels)
144-
full_intervals = build_full_intervals(query, labels)
145-
146-
json(conn, %{
147-
metric: metric,
148-
plot: plot_timeseries(timeseries_result, metric),
149-
labels: labels,
150-
comparison_plot: comparison_result && plot_timeseries(comparison_result, metric),
151-
comparison_labels: comparison_result && label_timeseries(comparison_result, nil),
152-
present_index: present_index,
153-
full_intervals: full_intervals
154-
})
155-
else
156-
{:error, message} when is_binary(message) -> bad_request(conn, message)
157-
end
158-
end
159-
160-
defp plot_timeseries(timeseries, metric) do
161-
Enum.map(timeseries, & &1[metric])
162-
end
163-
164-
defp label_timeseries(main_result, nil) do
165-
Enum.map(main_result, & &1.date)
166-
end
167-
168-
@blank_value "__blank__"
169-
defp label_timeseries(main_result, comparison_result) do
170-
blanks_to_fill = Enum.count(comparison_result) - Enum.count(main_result)
171-
172-
if blanks_to_fill > 0 do
173-
blanks = List.duplicate(@blank_value, blanks_to_fill)
174-
Enum.map(main_result, & &1.date) ++ blanks
175-
else
176-
Enum.map(main_result, & &1.date)
177-
end
178-
end
179-
180-
defp build_full_intervals(
181-
%Query{interval: "week"} = query,
182-
labels
183-
) do
184-
date_range = Query.date_range(query)
185-
build_intervals(labels, date_range, &Date.beginning_of_week/1, &Date.end_of_week/1)
186-
end
187-
188-
defp build_full_intervals(
189-
%Query{interval: "month"} = query,
190-
labels
191-
) do
192-
date_range = Query.date_range(query)
193-
build_intervals(labels, date_range, &Date.beginning_of_month/1, &Date.end_of_month/1)
194-
end
195-
196-
defp build_full_intervals(_query, _labels) do
197-
nil
198-
end
199-
200-
def build_intervals(labels, date_range, start_fn, end_fn) do
201-
for label <- labels, into: %{} do
202-
case Date.from_iso8601(label) do
203-
{:ok, date} ->
204-
interval_start = start_fn.(date)
205-
interval_end = end_fn.(date)
206-
207-
within_interval? =
208-
Enum.member?(date_range, interval_start) && Enum.member?(date_range, interval_end)
209-
210-
{label, within_interval?}
211-
212-
_ ->
213-
{label, false}
214-
end
215-
end
216-
end
217-
21850
def top_stats(conn, params) do
21951
site = conn.assigns[:site]
22052

@@ -265,52 +97,6 @@ defmodule PlausibleWeb.Api.StatsController do
26597
end
26698
end
26799

268-
defp present_index_for(site, query, dates) do
269-
case query.interval do
270-
"hour" ->
271-
current_date =
272-
DateTime.now!(site.timezone)
273-
|> Calendar.strftime("%Y-%m-%d %H:00:00")
274-
275-
Enum.find_index(dates, &(&1 == current_date))
276-
277-
"day" ->
278-
current_date =
279-
DateTime.now!(site.timezone)
280-
|> DateTime.to_date()
281-
|> Date.to_string()
282-
283-
Enum.find_index(dates, &(&1 == current_date))
284-
285-
"week" ->
286-
date_range = Query.date_range(query)
287-
288-
current_date =
289-
DateTime.now!(site.timezone)
290-
|> DateTime.to_date()
291-
|> Time.date_or_weekstart(date_range)
292-
|> Date.to_string()
293-
294-
Enum.find_index(dates, &(&1 == current_date))
295-
296-
"month" ->
297-
current_date =
298-
DateTime.now!(site.timezone)
299-
|> DateTime.to_date()
300-
|> Date.beginning_of_month()
301-
|> Date.to_string()
302-
303-
Enum.find_index(dates, &(&1 == current_date))
304-
305-
"minute" ->
306-
current_date =
307-
DateTime.now!(site.timezone)
308-
|> Calendar.strftime("%Y-%m-%d %H:%M:00")
309-
310-
Enum.find_index(dates, &(&1 == current_date))
311-
end
312-
end
313-
314100
defp fetch_top_stats(site, query) do
315101
goal_filter? =
316102
toplevel_goal_filter?(query)
@@ -1717,75 +1503,6 @@ defmodule PlausibleWeb.Api.StatsController do
17171503
end)
17181504
end
17191505

1720-
defp validate_interval(params) do
1721-
with %{"interval" => interval} <- params,
1722-
true <- Plausible.Stats.Interval.valid?(interval) do
1723-
:ok
1724-
else
1725-
%{} ->
1726-
:ok
1727-
1728-
false ->
1729-
values = Enum.join(Plausible.Stats.Interval.list(), ", ")
1730-
{:error, "Invalid value for interval. Accepted values are: #{values}"}
1731-
end
1732-
end
1733-
1734-
defp validate_interval_granularity(site, params, dates) do
1735-
case params do
1736-
%{"interval" => interval, "period" => "custom", "from" => _, "to" => _} ->
1737-
if Plausible.Stats.Interval.valid_for_period?("custom", interval,
1738-
site: site,
1739-
from: dates["from"],
1740-
to: dates["to"]
1741-
) do
1742-
:ok
1743-
else
1744-
{:error,
1745-
"Invalid combination of interval and period. Custom ranges over 12 months must come with greater granularity, e.g. `period=custom,interval=week`"}
1746-
end
1747-
1748-
%{"interval" => interval, "period" => period} ->
1749-
if Plausible.Stats.Interval.valid_for_period?(period, interval, site: site) do
1750-
:ok
1751-
else
1752-
{:error,
1753-
"Invalid combination of interval and period. Interval must be smaller than the selected period, e.g. `period=day,interval=minute`"}
1754-
end
1755-
1756-
_ ->
1757-
:ok
1758-
end
1759-
end
1760-
1761-
defp parse_and_validate_graph_metric(params, query) do
1762-
metric =
1763-
case params["metric"] do
1764-
nil -> :visitors
1765-
"conversions" -> :visitors
1766-
m -> Plausible.Stats.Metrics.from_string!(m)
1767-
end
1768-
1769-
requires_goal_filter? = metric in [:conversion_rate, :events]
1770-
has_goal_filter? = toplevel_goal_filter?(query)
1771-
1772-
requires_page_filter? = metric == :scroll_depth
1773-
1774-
has_page_filter? =
1775-
Filters.filtering_on_dimension?(query, "event:page", behavioral_filters: :ignore)
1776-
1777-
cond do
1778-
requires_goal_filter? and not has_goal_filter? ->
1779-
{:error, "Metric `#{metric}` can only be queried with a goal filter"}
1780-
1781-
requires_page_filter? and not has_page_filter? ->
1782-
{:error, "Metric `#{metric}` can only be queried with a page filter"}
1783-
1784-
true ->
1785-
{:ok, metric}
1786-
end
1787-
end
1788-
17891506
defp bad_request(conn, message, extra \\ %{}) do
17901507
payload = Map.merge(extra, %{error: message})
17911508

0 commit comments

Comments
 (0)