Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
105 lines
3.1 KiB
Elixir
105 lines
3.1 KiB
Elixir
defmodule TarakanWeb.LeaderboardLive do
|
|
use TarakanWeb, :live_view
|
|
|
|
alias Tarakan.Leaderboard
|
|
alias Tarakan.Profiles
|
|
|
|
@sorts %{
|
|
"reputation" => :reputation,
|
|
"reviews" => :reviews,
|
|
"findings" => :findings,
|
|
"verdicts" => :verdicts
|
|
}
|
|
|
|
@severities ~w(critical high medium low info)
|
|
@windows %{"7" => 7, "30" => 30, "90" => 90, "all" => :all}
|
|
|
|
@impl true
|
|
def mount(_params, _session, socket) do
|
|
{:ok,
|
|
socket
|
|
|> assign(:page_title, "Leaderboard")
|
|
|> assign(
|
|
:meta_description,
|
|
"Who's putting work on the public record: reports, findings, checks."
|
|
)
|
|
|> assign(:canonical_path, ~p"/leaderboard")}
|
|
end
|
|
|
|
@impl true
|
|
def handle_params(params, _uri, socket) do
|
|
sort = if is_map_key(@sorts, params["sort"]), do: params["sort"], else: "reputation"
|
|
severity = if params["severity"] in @severities, do: params["severity"], else: nil
|
|
window = if is_map_key(@windows, params["window"]), do: params["window"], else: "all"
|
|
|
|
{:noreply,
|
|
socket
|
|
|> assign(:sort, sort)
|
|
|> assign(:severity, severity)
|
|
|> assign(:window, window)
|
|
|> load_entries()}
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("sort", %{"by" => by}, socket) when is_map_key(@sorts, by) do
|
|
{:noreply, patch_filters(socket, %{sort: by})}
|
|
end
|
|
|
|
def handle_event("filter_severity", %{"severity" => severity}, socket) do
|
|
severity = if severity in @severities, do: severity, else: nil
|
|
{:noreply, patch_filters(socket, %{severity: severity})}
|
|
end
|
|
|
|
def handle_event("filter_window", %{"window" => window}, socket)
|
|
when is_map_key(@windows, window) do
|
|
{:noreply, patch_filters(socket, %{window: window})}
|
|
end
|
|
|
|
defp patch_filters(socket, updates) do
|
|
params =
|
|
%{
|
|
sort: socket.assigns.sort,
|
|
severity: socket.assigns.severity,
|
|
window: socket.assigns.window
|
|
}
|
|
|> Map.merge(updates)
|
|
# Keep the URL clean: defaults are implicit.
|
|
|> Map.reject(fn {key, value} ->
|
|
value in [nil, ""] or {key, value} in [sort: "reputation", window: "all"]
|
|
end)
|
|
|
|
push_patch(socket, to: ~p"/leaderboard?#{params}")
|
|
end
|
|
|
|
defp load_entries(socket) do
|
|
opts = [
|
|
severity: socket.assigns.severity,
|
|
window: Map.fetch!(@windows, socket.assigns.window)
|
|
]
|
|
|
|
entries = Leaderboard.top(Map.fetch!(@sorts, socket.assigns.sort), opts)
|
|
|
|
socket
|
|
|> assign(:entries, entries)
|
|
|> assign(:badges, Profiles.badges_for(Enum.map(entries, & &1.account.id)))
|
|
end
|
|
|
|
@doc false
|
|
def tier_label("reviewer"), do: "Reviewer"
|
|
def tier_label("contributor"), do: "Contributor"
|
|
def tier_label(_new), do: "New"
|
|
|
|
@doc false
|
|
def badge_label(:first_blood), do: "First blood"
|
|
def badge_label(:century), do: "Century"
|
|
def badge_label(:eradicator), do: "Eradicator"
|
|
def badge_label(:exorcist), do: "Exorcist"
|
|
def badge_label(:sharpshooter), do: "Sharpshooter"
|
|
def badge_label(badge), do: badge |> to_string() |> String.replace("_", " ")
|
|
|
|
@doc false
|
|
def rank_style(1), do: "text-signal"
|
|
def rank_style(2), do: "text-ink"
|
|
def rank_style(3), do: "text-ink-muted"
|
|
def rank_style(_), do: "text-ink-faint"
|
|
end
|