diff options
author | Yorhel <git@yorhel.nl> | 2020-01-08 09:07:26 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2020-01-08 09:07:26 +0100 |
commit | 788ff22a82cd16c5bc31f70a25118a99372bcb5f (patch) | |
tree | 5857f959c131ba8364940264757a18ee0dc6fb85 /lib | |
parent | 5b1e69fb1972b00a7e8c154d84a0885c2c4bf95f (diff) |
v2rw: Convert tag link browser
Diffstat (limited to 'lib')
-rw-r--r-- | lib/VNDB/Handler/Tags.pm | 115 | ||||
-rw-r--r-- | lib/VNWeb/HTML.pm | 2 | ||||
-rw-r--r-- | lib/VNWeb/Prelude.pm | 8 | ||||
-rw-r--r-- | lib/VNWeb/Tags/Links.pm | 144 |
4 files changed, 149 insertions, 120 deletions
diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm index cbc7b293..9e771997 100644 --- a/lib/VNDB/Handler/Tags.pm +++ b/lib/VNDB/Handler/Tags.pm @@ -15,7 +15,6 @@ TUWF::register( qr{g([1-9]\d*)/(add)}, \&tagedit, qr{g/new}, \&tagedit, qr{g/list}, \&taglist, - qr{g/links}, \&taglinks, qr{v([1-9]\d*)/tagmod}, \&vntagmod, qr{u([1-9]\d*)/tags}, \&usertags, qr{g}, \&tagindex, @@ -380,120 +379,6 @@ sub taglist { } -sub taglinks { - my $self = shift; - - my $f = $self->formValidate( - { get => 'p', required => 0, default => 1, template => 'page' }, - { get => 'o', required => 0, default => 'd', enum => ['a', 'd'] }, - { get => 's', required => 0, default => 'date', enum => [qw|date tag|] }, - { get => 'v', required => 0, default => 0, template => 'id' }, - { get => 'u', required => 0, default => 0, template => 'id' }, - { get => 't', required => 0, default => 0, template => 'id' }, - ); - return $self->resNotFound if $f->{_err} || $f->{p} > 100; - - my($list, $np) = $self->dbTagLinks( - what => 'details', - results => 50, - page => $f->{p}, - sort => $f->{s}, - reverse => $f->{o} eq 'd', - $f->{v} ? (vid => $f->{v}) : (), - $f->{u} ? (uid => $f->{u}) : (), - $f->{t} ? (tag => $f->{t}) : (), - ); - - my $url = sub { - my %f = ((map +($_,$f->{$_}), qw|s o v u t|), @_); - my $qs = join ';', map $f{$_}?"$_=$f{$_}":(), keys %f; - return '/g/links'.($qs?"?$qs":'') - }; - - $self->htmlHeader(noindex => 1, title => 'Tag link browser'); - div class => 'mainbox'; - h1 'Tag link browser'; - - div class => 'warning'; - h2 'Spoiler warning'; - p 'This list displays the tag votes of individual users. Spoilery tags are not hidden, and may not even be correctly flagged as such.'; - end; - br; - - if($f->{u} || $f->{t} || $f->{v}) { - p 'Active filters:'; - ul; - if($f->{u}) { - my $o = $self->dbUserGet(uid => $f->{u})->[0]; - li; - txt '['; a href => $url->(u=>0), 'remove'; txt '] '; - txt 'User: '; - VNWeb::HTML::user_($o); - end; - } - if($f->{t}) { - my $o = $self->dbTagGet(id => $f->{t})->[0]; - li; - txt '['; a href => $url->(t=>0), 'remove'; txt '] '; - txt 'Tag:'; txt ' '; - a href => "/g$f->{t}", $o->{name}||'Unknown tag'; - end; - } - if($f->{v}) { - my $o = $self->dbVNGet(id => $f->{v})->[0]; - li; - txt '['; a href => $url->(v=>0), 'remove'; txt '] '; - txt 'Visual novel:'; txt ' '; - a href => "/v$f->{v}", $o->{title}||'Unknown VN'; - end; - } - end 'ul'; - } - p 'Click the arrow beside a user, tag or VN to add it as a filter.' unless $f->{v} && $f->{u} && $f->{t}; - end 'div'; - - $self->htmlBrowse( - class => 'taglinks', - options => $f, - nextpage => $np, - items => $list, - pageurl => $url->(), - sorturl => $url->(s=>0,o=>0), - header => [ - [ 'Date', 'date' ], - [ 'User' ], - [ 'Rating' ], - [ 'Tag', 'tag' ], - [ 'Spoiler' ], - [ 'Visual novel' ], - ], - row => sub { - my($s, $n, $l) = @_; - Tr; - td class => 'tc1', fmtdate $l->{date}; - td class => 'tc2'; - a href => $url->(u=>$l->{uid}), class => 'setfil', '> ' if $l->{user_id} && !$f->{u}; - VNWeb::HTML::user_($l); - end; - td class => 'tc3'.($l->{ignore}?' ignored':''); - tagscore $l->{vote}; - end; - td class => 'tc4'; - a href => $url->(t=>$l->{tag}), class => 'setfil', '> ' if !$f->{t}; - a href => "/g$l->{tag}", $l->{name}; - end; - td class => 'tc5', !defined $l->{spoiler} ? ' ' : fmtspoil $l->{spoiler}; - td class => 'tc6'; - a href => $url->(v=>$l->{vid}), class => 'setfil', '> ' if !$f->{v}; - a href => "/v$l->{vid}", shorten $l->{title}, 50; - end; - end; - }, - ); - $self->htmlFooter; -} - - sub vntagmod { my($self, $vid) = @_; diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm index 1d6731c2..066cbde9 100644 --- a/lib/VNWeb/HTML.pm +++ b/lib/VNWeb/HTML.pm @@ -47,7 +47,7 @@ sub clearfloat_ { div_ class => 'clearfloat', '' } sub debug_ { return if !tuwf->debug; # This provides a nice JSON browser in FF, not sure how other browsers render it. - my $data = uri_escape(JSON::XS->new->canonical->encode($_[0])); + my $data = uri_escape(JSON::XS->new->canonical->allow_nonref->encode($_[0])); a_ style => 'margin: 0 5px', title => 'Debug', href => 'data:application/json,'.$data, ' ⚙ '; } diff --git a/lib/VNWeb/Prelude.pm b/lib/VNWeb/Prelude.pm index 64ef289c..3f5d5f67 100644 --- a/lib/VNWeb/Prelude.pm +++ b/lib/VNWeb/Prelude.pm @@ -8,13 +8,13 @@ # use Exporter 'import'; # use Time::HiRes 'time'; # use List::Util 'min', 'max', 'sum'; -# use POSIX 'ceil'; +# use POSIX 'ceil', 'floor'; # # use VNDBUtil; # use VNDB::BBCode; # use VNDB::Types; # use VNDB::Config; -# use VNDB::Func 'fmtdate', 'fmtage', 'fmtvote', 'query_encode'; +# use VNDB::Func 'fmtdate', 'fmtage', 'fmtvote', 'fmtspoil', 'query_encode'; # use VNDB::ExtLinks; # use VNWeb::Auth; # use VNWeb::HTML; @@ -52,13 +52,13 @@ sub import { use Exporter 'import'; use Time::HiRes 'time'; use List::Util 'min', 'max', 'sum'; - use POSIX 'ceil'; + use POSIX 'ceil', 'floor'; use VNDBUtil; use VNDB::BBCode; use VNDB::Types; use VNDB::Config; - use VNDB::Func 'fmtdate', 'fmtage', 'fmtvote', 'query_encode'; + use VNDB::Func 'fmtdate', 'fmtage', 'fmtvote', 'fmtspoil', 'query_encode'; use VNDB::ExtLinks; use VNWeb::Auth; use VNWeb::HTML; diff --git a/lib/VNWeb/Tags/Links.pm b/lib/VNWeb/Tags/Links.pm new file mode 100644 index 00000000..81d8e128 --- /dev/null +++ b/lib/VNWeb/Tags/Links.pm @@ -0,0 +1,144 @@ +package VNWeb::Tags::Links; + +use VNWeb::Prelude; + + +# XXX: This is ugly, both in code and UI. Not sure what to replace it with. +sub tagscore_ { + my $s = shift; + div_ class => 'taglvl', style => sprintf('width: %.0fpx', ($s-floor($s))*10), ' ' if $s < 0 && $s-floor($s) > 0; + for(-3..3) { + if($_ < 0) { + if($s > 0 || floor($s) > $_) { + div_ class => "taglvl taglvl$_", ' '; + } elsif(floor($s) != $_) { + div_ class => "taglvl taglvl$_ taglvlsel", ' '; + } else { + div_ class => "taglvl taglvl$_ taglvlsel", style => sprintf('width: %.0fpx', 10-($s-$_)*10), ' '; + } + } elsif($_ > 0) { + if($s < 0 || ceil($s) < $_) { + div_ class => "taglvl taglvl$_", ' '; + } elsif(ceil($s) != $_) { + div_ class => "taglvl taglvl$_ taglvlsel", ' '; + } else { + div_ class => "taglvl taglvl$_ taglvlsel", style => sprintf('width: %.0fpx', 10-($_-$s)*10), ' '; + } + } else { + div_ class => "taglvl taglvl0", sprintf '%.1f', $s; + } + } + div_ class => 'taglvl', style => sprintf('width: %.0fpx', (ceil($s)-$s)*10), ' ' if $s > 0 && ceil($s)-$s > 0; +} + + +sub listing_ { + my($opt, $lst, $np, $url) = @_; + + paginate_ $url, $opt->{p}, $np, 't'; + div_ class => 'mainbox browse taglinks', sub { + table_ class => 'stripe', sub { + thead_ sub { tr_ sub { + td_ class => 'tc1', sub { txt_ 'Date'; sortable_ 'date', $opt, $url; debug_ $lst; }; + td_ class => 'tc2', 'User'; + td_ class => 'tc3', 'Rating'; + td_ class => 'tc4', sub { txt_ 'Tag'; sortable_ 'tag', $opt, $url }; + td_ class => 'tc5', 'Spoiler'; + td_ class => 'tc6', 'Visual novel'; + }}; + tr_ sub { + my $i = $_; + td_ class => 'tc1', fmtdate $i->{date}; + td_ class => 'tc2', sub { + a_ href => $url->(u => $i->{uid}, p=>undef), class => 'setfil', '> ' if !defined $opt->{u}; + user_ $i; + }; + td_ mkclass(tc3 => 1, ignored => $i->{ignored}), sub { tagscore_ $i->{vote} }; + td_ class => 'tc4', sub { + a_ href => $url->(t => $i->{uid}, p=>undef), class => 'setfil', '> ' if !defined $opt->{t}; + a_ href => "/g$i->{tag}", $i->{name}; + }; + td_ class => 'tc5', !defined $i->{spoiler} ? '' : fmtspoil $i->{spoiler}; + td_ class => 'tc6', sub { + a_ href => $url->(v => $i->{vid}, p=>undef), class => 'setfil', '> ' if !defined $opt->{v}; + a_ href => "/v$i->{vid}", shorten $i->{title}, 50; + }; + } for @$lst; + }; + }; + paginate_ $url, $opt->{p}, $np, 'b'; +} + + +TUWF::get qr{/g/links}, sub { + my $opt = tuwf->validate(get => + p => { page => 1 }, + o => { onerror => 'd', enum => ['a', 'd'] }, + s => { onerror => 'date', enum => [qw|date tag|] }, + v => { onerror => undef, id => 1 }, + u => { onerror => undef, id => 1 }, + t => { onerror => undef, id => 1 }, + )->data; + + my $where = sql_and + defined $opt->{v} ? sql('tv.vid =', \$opt->{v}) : (), + defined $opt->{u} ? sql('tv.uid =', \$opt->{u}) : (), + defined $opt->{t} ? sql('tv.tag =', \$opt->{t}) : (); + + my $filt = defined $opt->{u} || defined $opt->{t} || defined $opt->{v}; + + my $count = $filt && tuwf->dbVali('SELECT COUNT(*) FROM tags_vn tv WHERE', $where); + my($lst, $np) = tuwf->dbPagei({ page => $opt->{p}, results => 50 }, ' + SELECT tv.vid, tv.uid, tv.tag, tv.vote, tv.spoiler,', sql_totime('tv.date'), 'as date, tv.ignore, v.title,', sql_user(), ', t.name + FROM tags_vn tv + JOIN vn v ON v.id = tv.vid + JOIN users u ON u.id = tv.uid + JOIN tags t ON t.id = tv.tag + WHERE', $where, ' + ORDER BY', { date => 'tv.date', tag => 't.name' }->{$opt->{s}}, { a => 'ASC', d => 'DESC' }->{$opt->{o}} + ); + $np = [ $count, 50 ] if $count; + + my sub url { '?'.query_encode %$opt, @_ } + + framework_ title => 'Tag link browser', sub { + div_ class => 'mainbox', sub { + h1_ 'Tag link browser'; + div_ class => 'warning', sub { + h2_ 'Spoiler warning'; + p_ 'This list displays the tag votes of individual users. Spoilery tags are not hidden, and may not even be correctly flagged as such.'; + }; + br_; + if($filt) { + p_ 'Active filters:'; + ul_ sub { + li_ sub { + txt_ '['; a_ href => url(u=>undef, p=>undef), 'remove'; txt_ '] '; + txt_ 'User: '; + user_ tuwf->dbRowi('SELECT', sql_user(), 'FROM users u WHERE id=', \$opt->{u}); + } if defined $opt->{u}; + li_ sub { + txt_ '['; a_ href => url(t=>undef, p=>undef), 'remove'; txt_ '] '; + txt_ 'Tag:'; txt_ ' '; + a_ href => "/g$opt->{t}", tuwf->dbVali('SELECT name FROM tags WHERE id=', \$opt->{t})||'Unknown tag'; + } if defined $opt->{t}; + li_ sub { + txt_ '['; a_ href => url(v=>undef, p=>undef), 'remove'; txt_ '] '; + txt_ 'Visual novel'; txt_ ' '; + a_ href => "/v$opt->{v}", tuwf->dbVali('SELECT title FROM vn WHERE id=', \$opt->{v})||'Unknown VN'; + } if defined $opt->{v}; + } + } + if($lst && @$lst) { + p_ 'Click the arrow before a user, tag or VN to add it as a filter.' + if !defined $opt->{u} && !defined $opt->{t} && !defined $opt->{v}; + } else { + p_ 'No tag votes matching the requested filters.'; + } + }; + + listing_ $opt, $lst, $np, \&url if $lst && @$lst; + }; +}; + +1; |