diff options
Diffstat (limited to 'lib/VN3/User/Page.pm')
-rw-r--r-- | lib/VN3/User/Page.pm | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/lib/VN3/User/Page.pm b/lib/VN3/User/Page.pm new file mode 100644 index 00000000..b89c51fb --- /dev/null +++ b/lib/VN3/User/Page.pm @@ -0,0 +1,207 @@ +package VN3::User::Page; + +use VN3::Prelude; +use VN3::User::Lib; + + +sub StatsLeft { + my $u = shift; + my $vns = show_list($u) && tuwf->dbVali('SELECT COUNT(*) FROM vnlists WHERE uid =', \$u->{id}); + my $rel = show_list($u) && tuwf->dbVali('SELECT COUNT(*) FROM rlists WHERE uid =', \$u->{id}); + my $posts = tuwf->dbVali('SELECT COUNT(*) FROM threads_posts WHERE uid =', \$u->{id}); + my $threads = tuwf->dbVali('SELECT COUNT(*) FROM threads_posts WHERE num = 1 AND uid =', \$u->{id}); + + Div class => 'card__title mb-4', 'Stats'; + Div class => 'big-stats mb-5', sub { + A href => "/u$u->{id}/list", class => 'big-stats__stat', sub { + Txt 'Votes'; + Div class => 'big-stats__value', show_list($u) ? $u->{c_votes} : '-'; + }; + A href => "/u$u->{id}/hist", class => 'big-stats__stat', sub { + Txt 'Edits'; + Div class => 'big-stats__value', $u->{c_changes}; + }; + A href => "/g/links?u=$u->{id}", class => 'big-stats__stat', sub { + Txt 'Tags'; + Div class => 'big-stats__value', $u->{c_tags}; + }; + }; + Div class => 'user-stats__text', sub { + Dl class => 'dl--horizontal', sub { + if(show_list $u) { + Dt 'List stats'; + Dd sprintf '%d release%s of %d visual novel%s', $rel, $rel == 1 ? '' : 's', $vns, $vns == 1 ? '' : 's'; + } + Dt 'Forum stats'; + Dd sprintf '%d post%s, %d new thread%s', $posts, $posts == 1 ? '' : 's', $threads, $threads == 1 ? '' : 's'; + Dt 'Registered'; + Dd date_display $u->{registered}; + }; + }; +} + + +sub Stats { + my $u = shift; + + my($count, $Graph) = show_list($u) ? VoteGraph u => $u->{id} : (); + + Div class => 'card card--white card--no-separators flex-expand mb-5', sub { + Div class => 'card__section fs-medium', sub { + Div class => 'user-stats', sub { + Div class => 'user-stats__left', sub { StatsLeft $u }; + Div class => 'user-stats__right', sub { + Div class => 'card__title mb-2', 'Vote distribution'; + $Graph->(); + } if $count; + } + } + } +} + + +sub List { + my $u = shift; + return if !show_list $u; + + # XXX: This query doesn't catch vote or list *changes*, only new entries. + # We don't store the modification date in the DB at the moment. + my $l = tuwf->dbAlli(q{ + SELECT il.vid, EXTRACT('epoch' FROM GREATEST(v.date, l.added)) AS date, vn.title, vn.original, v.vote, l.status + FROM ( + SELECT vid FROM votes WHERE uid = }, \$u->{id}, q{ + UNION SELECT vid FROM vnlists WHERE uid = }, \$u->{id}, q{ + ) AS il (vid) + LEFT JOIN votes v ON v.vid = il.vid + LEFT JOIN vnlists l ON l.vid = il.vid + JOIN vn ON vn.id = il.vid + WHERE v.uid = }, \$u->{id}, q{ + AND l.uid = }, \$u->{id}, q{ + ORDER BY GREATEST(v.date, l.added) DESC + LIMIT 10 + }); + return if !@$l; + + Div class => 'card card--white card--no-separators mb-5', sub { + Div class => 'card__header', sub { + Div class => 'card__title', 'Recent list additions'; + }; + Table class => 'table table--responsive-single-sm fs-medium', sub { + Thead sub { + Tr sub { + Th width => '15%', 'Date'; + Th width => '50%', 'Visual novel'; + Th width => '10%', 'Vote'; + Th width => '25%', 'Status'; + }; + }; + Tbody sub { + for my $i (@$l) { + Tr sub { + Td class => 'tabular-nums muted', date_display $i->{date}; + Td sub { + A href => "/v$i->{vid}", title => $i->{original}||$i->{title}, $i->{title}; + }; + Td vote_display $i->{vote}; + Td $i->{status} ? $VNLIST_STATUS[$i->{status}] : ''; + }; + } + }; + }; + Div class => 'card__section fs-medium', sub { + A href => "/u$u->{id}/list", 'View full list'; + } + }; +} + + +sub Edits { + my $u = shift; + # XXX: This is a lazy implementation, could probably share code/UI with the database entry history tables (as in VNDB 2) + + my $l = tuwf->dbAlli(q{ + SELECT ch.id, ch.itemid, ch.rev, ch.type, EXTRACT('epoch' FROM ch.added) AS added + FROM changes ch + WHERE ch.requester =}, \$u->{id}, q{ + ORDER BY ch.added DESC LIMIT 10 + }); + return if !@$l; + + # This can also be written as a UNION, haven't done any benchmarking yet. + # It doesn't matter much with only 10 entries, but it will matter if this + # query is re-used for other history browsing purposes. + enrich id => q{ + SELECT ch.id, COALESCE(d.title, v.title, p.name, r.title, c.name, sa.name) AS title + FROM changes ch + LEFT JOIN docs_hist d ON ch.type = 'd' AND d.chid = ch.id + LEFT JOIN vn_hist v ON ch.type = 'v' AND v.chid = ch.id + LEFT JOIN producers_hist p ON ch.type = 'p' AND p.chid = ch.id + LEFT JOIN releases_hist r ON ch.type = 'r' AND r.chid = ch.id + LEFT JOIN chars_hist c ON ch.type = 'c' AND c.chid = ch.id + LEFT JOIN staff_hist s ON ch.type = 's' AND s.chid = ch.id + LEFT JOIN staff_alias_hist sa ON ch.type = 's' AND sa.chid = ch.id AND s.aid = sa.aid + WHERE ch.id IN}, $l; + + Div class => 'card card--white card--no-separators mb-5', sub { + Div class => 'card__header', sub { + Div class => 'card__title', 'Recent database contributions'; + }; + Table class => 'table table--responsive-single-sm fs-medium', sub { + Thead sub { + Tr sub { + Th width => '15%', 'Date'; + Th width => '10%', 'Rev.'; + Th width => '75%', 'Entry'; + }; + }; + Tbody sub { + for my $i (@$l) { + my $id = "$i->{type}$i->{itemid}.$i->{rev}"; + Tr sub { + Td class => 'tabular-nums muted', date_display $i->{added}; + Td sub { + A href => "/$id", $id; + }; + Td sub { + A href => "/$id", $i->{title}; + }; + } + } + } + }; + Div class => 'card__section fs-medium', sub { + A href => "/u$u->{id}/hist", 'View all'; + } + }; +} + + +TUWF::get qr{/$UID_RE}, sub { + my $uid = tuwf->capture('id'); + my $u = tuwf->dbRowi(q{ + SELECT u.id, u.username, EXTRACT('epoch' FROM u.registered) AS registered, u.c_votes, u.c_changes, u.c_tags, hd.value AS hide_list + FROM users u + LEFT JOIN users_prefs hd ON hd.uid = u.id AND hd.key = 'hide_list' + WHERE u.id =}, \$uid + ); + return tuwf->resNotFound if !$u->{id}; + + Framework + title => lcfirst($u->{username}), + index => 0, + single_col => 1, + top => sub { + Div class => 'col-md', sub { + EntryEdit u => $u; + Div class => 'detail-page-title', ucfirst $u->{username}; + TopNav details => $u; + } + }, + sub { + Stats $u; + List $u; + Edits $u; + }; +}; + +1; |