-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathdashboard.ex
More file actions
134 lines (106 loc) · 3.57 KB
/
dashboard.ex
File metadata and controls
134 lines (106 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
defmodule ErrorTracker.Web.Live.Dashboard do
@moduledoc false
use ErrorTracker.Web, :live_view
import Ecto.Query
alias ErrorTracker.Error
alias ErrorTracker.Repo
alias ErrorTracker.Web.Search
@per_page 10
@impl Phoenix.LiveView
def handle_params(params, uri, socket) do
path = struct(URI, uri |> URI.parse() |> Map.take([:path, :query]))
{:noreply,
socket
|> assign(
path: path,
search: Search.from_params(params),
page: 1,
search_form: Search.to_form(params)
)
|> paginate_errors()}
end
@impl Phoenix.LiveView
def handle_event("search", params, socket) do
search = Search.from_params(params["search"] || %{})
%URI{} = path = socket.assigns.path
path_w_filters = %{path | query: URI.encode_query(search)}
{:noreply, push_patch(socket, to: URI.to_string(path_w_filters))}
end
@impl Phoenix.LiveView
def handle_event("next-page", _params, socket) do
{:noreply, socket |> assign(page: socket.assigns.page + 1) |> paginate_errors()}
end
@impl Phoenix.LiveView
def handle_event("prev-page", _params, socket) do
{:noreply, socket |> assign(page: socket.assigns.page - 1) |> paginate_errors()}
end
@impl Phoenix.LiveView
def handle_event("resolve", %{"error_id" => id}, socket) do
error = Repo.get(Error, id)
{:ok, _resolved} = ErrorTracker.resolve(error)
{:noreply, paginate_errors(socket)}
end
@impl Phoenix.LiveView
def handle_event("unresolve", %{"error_id" => id}, socket) do
error = Repo.get(Error, id)
{:ok, _unresolved} = ErrorTracker.unresolve(error)
{:noreply, paginate_errors(socket)}
end
@impl Phoenix.LiveView
def handle_event("mute", %{"error_id" => id}, socket) do
error = Repo.get(Error, id)
{:ok, _muted} = ErrorTracker.mute(error)
{:noreply, paginate_errors(socket)}
end
@impl Phoenix.LiveView
def handle_event("unmute", %{"error_id" => id}, socket) do
error = Repo.get(Error, id)
{:ok, _unmuted} = ErrorTracker.unmute(error)
{:noreply, paginate_errors(socket)}
end
defp paginate_errors(socket) do
%{page: page, search: search} = socket.assigns
offset = (page - 1) * @per_page
query = filter(Error, search)
total_errors = Repo.aggregate(query, :count)
errors =
Repo.all(
from query,
order_by: [desc: :last_occurrence_at],
offset: ^offset,
limit: @per_page
)
error_ids = Enum.map(errors, & &1.id)
occurrences =
if errors != [] do
errors
|> Ecto.assoc(:occurrences)
|> where([o], o.error_id in ^error_ids)
|> group_by([o], o.error_id)
|> select([o], {o.error_id, count(o.id)})
|> Repo.all()
else
[]
end
assign(socket,
errors: errors,
occurrences: Map.new(occurrences),
total_pages: (total_errors / @per_page) |> Float.ceil() |> trunc
)
end
defp filter(query, search) do
Enum.reduce(search, query, &do_filter/2)
end
defp do_filter({:status, status}, query) do
where(query, [error], error.status == ^status)
end
defp do_filter({field, value}, query) do
# Postgres provides the ILIKE operator which produces a case-insensitive match between two
# strings. SQLite3 only supports LIKE, which is case-insensitive for ASCII characters.
Repo.with_adapter(fn
:postgres -> where(query, [error], ilike(field(error, ^field), ^"%#{value}%"))
:mysql -> where(query, [error], like(field(error, ^field), ^"%#{value}%"))
:sqlite -> where(query, [error], like(field(error, ^field), ^"%#{value}%"))
end)
end
end