mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-20 06:37: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 PhilomenaWeb.ImageLoader
|
||||||
alias Philomena.Textile.Renderer
|
alias Philomena.Textile.Renderer
|
||||||
|
alias Philomena.UserStatistics.UserStatistic
|
||||||
alias Philomena.Users.User
|
alias Philomena.Users.User
|
||||||
alias Philomena.Galleries.Gallery
|
alias Philomena.Galleries.Gallery
|
||||||
alias Philomena.Posts.Post
|
alias Philomena.Posts.Post
|
||||||
|
@ -82,6 +83,8 @@ defmodule PhilomenaWeb.ProfileController do
|
||||||
|> limit(5)
|
|> limit(5)
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
|
|
||||||
|
statistics = calculate_statistics(user)
|
||||||
|
|
||||||
interactions =
|
interactions =
|
||||||
Interactions.user_interactions([recent_uploads, recent_faves], current_user)
|
Interactions.user_interactions([recent_uploads, recent_faves], current_user)
|
||||||
|
|
||||||
|
@ -95,7 +98,38 @@ defmodule PhilomenaWeb.ProfileController do
|
||||||
recent_comments: recent_comments,
|
recent_comments: recent_comments,
|
||||||
recent_posts: recent_posts,
|
recent_posts: recent_posts,
|
||||||
recent_galleries: recent_galleries,
|
recent_galleries: recent_galleries,
|
||||||
|
statistics: statistics,
|
||||||
layout_class: "layout--wide"
|
layout_class: "layout--wide"
|
||||||
)
|
)
|
||||||
end
|
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
|
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)
|
= pretty_time(award.awarded_on)
|
||||||
|
|
||||||
.column-layout__main
|
.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 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_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
|
= 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)
|
Canada.Can.can?(conn.assigns.current_user, action, model)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def number_with_delimiter(nil), do: "0"
|
||||||
def number_with_delimiter(number) do
|
def number_with_delimiter(number) do
|
||||||
number
|
number
|
||||||
|> to_charlist()
|
|> to_charlist()
|
||||||
|
|
|
@ -17,6 +17,33 @@ defmodule PhilomenaWeb.ProfileView do
|
||||||
def award_title(award),
|
def award_title(award),
|
||||||
do: award.badge_name
|
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
|
defp badge_url_root do
|
||||||
Application.get_env(:philomena, :badge_url_root)
|
Application.get_env(:philomena, :badge_url_root)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue