mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-19 14:17:59 +01:00
generate statistics sparklines
This commit is contained in:
parent
d8e3b9e4ff
commit
6882dd00e3
5 changed files with 91 additions and 0 deletions
|
@ -3,6 +3,7 @@ defmodule PhilomenaWeb.ProfileController do
|
|||
|
||||
alias PhilomenaWeb.ImageLoader
|
||||
alias Philomena.Textile.Renderer
|
||||
alias Philomena.UserStatistics.UserStatistic
|
||||
alias Philomena.Users.User
|
||||
alias Philomena.Galleries.Gallery
|
||||
alias Philomena.Posts.Post
|
||||
|
@ -82,6 +83,8 @@ defmodule PhilomenaWeb.ProfileController do
|
|||
|> limit(5)
|
||||
|> Repo.all()
|
||||
|
||||
statistics = calculate_statistics(user)
|
||||
|
||||
interactions =
|
||||
Interactions.user_interactions([recent_uploads, recent_faves], current_user)
|
||||
|
||||
|
@ -95,7 +98,38 @@ defmodule PhilomenaWeb.ProfileController do
|
|||
recent_comments: recent_comments,
|
||||
recent_posts: recent_posts,
|
||||
recent_galleries: recent_galleries,
|
||||
statistics: statistics,
|
||||
layout_class: "layout--wide"
|
||||
)
|
||||
end
|
||||
|
||||
defp calculate_statistics(user) do
|
||||
now =
|
||||
DateTime.utc_now()
|
||||
|> DateTime.to_unix(:second)
|
||||
|> div(86400)
|
||||
|
||||
last_90 =
|
||||
UserStatistic
|
||||
|> where(user_id: ^user.id)
|
||||
|> where([us], us.day > ^(now - 89))
|
||||
|> Repo.all()
|
||||
|> Map.new(&{&1.day, &1})
|
||||
|
||||
%{
|
||||
uploads: individual_stat(last_90, :uploads),
|
||||
images_favourited: individual_stat(last_90, :images_favourited),
|
||||
comments_posted: individual_stat(last_90, :comments_posted),
|
||||
votes_cast: individual_stat(last_90, :votes_cast),
|
||||
metadata_updates: individual_stat(last_90, :metadata_updates),
|
||||
forum_posts: individual_stat(last_90, :forum_posts)
|
||||
}
|
||||
end
|
||||
|
||||
defp individual_stat(mapping, stat_name) do
|
||||
Enum.map((89..0), &map_fetch(mapping[&1], stat_name) || 0)
|
||||
end
|
||||
|
||||
defp map_fetch(nil, _field_name), do: nil
|
||||
defp map_fetch(map, field_name), do: Map.get(map, field_name)
|
||||
end
|
||||
|
|
28
lib/philomena_web/templates/profile/_statistics.html.slime
Normal file
28
lib/philomena_web/templates/profile/_statistics.html.slime
Normal file
|
@ -0,0 +1,28 @@
|
|||
.block
|
||||
.block__header: span.block__header__title Statistics
|
||||
.block__content
|
||||
table.table.table--stats.center
|
||||
tr
|
||||
td.table--stats__parameter Uploads
|
||||
td.table--stats__value = number_with_delimiter(@user.uploads_count)
|
||||
td.table--stats__sparkline: .sparkline = sparkline_data(@statistics.uploads)
|
||||
tr
|
||||
td.table--stats__parameter Favorites
|
||||
td.table--stats__value = number_with_delimiter(@user.images_favourited_count)
|
||||
td.table--stats__sparkline: .sparkline = sparkline_data(@statistics.images_favourited)
|
||||
tr
|
||||
td.table--stats__parameter Comments
|
||||
td.table--stats__value = number_with_delimiter(@user.comments_posted_count)
|
||||
td.table--stats__sparkline: .sparkline = sparkline_data(@statistics.comments_posted)
|
||||
tr
|
||||
td.table--stats__parameter Votes
|
||||
td.table--stats__value = number_with_delimiter(@user.votes_cast_count)
|
||||
td.table--stats__sparkline: .sparkline = sparkline_data(@statistics.votes_cast)
|
||||
tr
|
||||
td.table--stats__parameter Metadata Updates
|
||||
td.table--stats__value = number_with_delimiter(@user.metadata_updates_count)
|
||||
td.table--stats__sparkline: .sparkline = sparkline_data(@statistics.metadata_updates)
|
||||
tr
|
||||
td.table--stats__parameter Forum Posts
|
||||
td.table--stats__value = number_with_delimiter(@user.forum_posts_count)
|
||||
td.table--stats__sparkline: .sparkline = sparkline_data(@statistics.forum_posts)
|
|
@ -51,6 +51,7 @@
|
|||
= pretty_time(award.awarded_on)
|
||||
|
||||
.column-layout__main
|
||||
= render PhilomenaWeb.ProfileView, "_statistics.html", user: @user, statistics: @statistics, conn: @conn
|
||||
= render PhilomenaWeb.ProfileView, "_recent_images.html", title: "Recent Uploads", images: @recent_uploads, view_all_path: Routes.search_path(@conn, :index, q: "uploader_id:#{@user.id}"), conn: @conn
|
||||
= render PhilomenaWeb.ProfileView, "_recent_images.html", title: "Recent Favorites", images: @recent_faves, view_all_path: Routes.search_path(@conn, :index, q: "faved_by_id:#{@user.id}"), conn: @conn
|
||||
= render PhilomenaWeb.ProfileView, "_recent_galleries.html", galleries: @recent_galleries, user: @user, conn: @conn
|
||||
|
|
|
@ -64,6 +64,7 @@ defmodule PhilomenaWeb.AppView do
|
|||
Canada.Can.can?(conn.assigns.current_user, action, model)
|
||||
end
|
||||
|
||||
def number_with_delimiter(nil), do: "0"
|
||||
def number_with_delimiter(number) do
|
||||
number
|
||||
|> to_charlist()
|
||||
|
|
|
@ -17,6 +17,33 @@ defmodule PhilomenaWeb.ProfileView do
|
|||
def award_title(award),
|
||||
do: award.badge_name
|
||||
|
||||
def sparkline_data(data) do
|
||||
# Normalize range
|
||||
{min, max} = Enum.min_max(data)
|
||||
max = max(max, 0)
|
||||
min = max(min, 0)
|
||||
|
||||
content_tag :svg, [width: "100%", preserveAspectRatio: "none", viewBox: "0 0 90 20"] do
|
||||
for {val, i} <- Enum.with_index(data) do
|
||||
# Filter out negative values
|
||||
calc = max(val, 0)
|
||||
|
||||
# Lerp or 0 if not present
|
||||
height = zero_div((calc - min) * 20, max - min)
|
||||
|
||||
# In SVG coords, y grows down
|
||||
y = 20 - height
|
||||
|
||||
content_tag :rect, [class: "barline__bar", x: i, y: y, width: 1, height: height] do
|
||||
content_tag :title, val
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp zero_div(_num, 0), do: 0
|
||||
defp zero_div(num, den), do: div(num, den)
|
||||
|
||||
defp badge_url_root do
|
||||
Application.get_env(:philomena, :badge_url_root)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue