summaryrefslogtreecommitdiff
path: root/lib/VNWeb/TT/TagPage.pm
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2021-01-09 09:41:55 +0100
committerYorhel <git@yorhel.nl>2021-01-09 11:02:18 +0100
commit1ec958ba9d2e40c65246bd29f28b2b50364b2a5a (patch)
treed25ef02ca17f339bfc773f648c7392f5a5ae757e /lib/VNWeb/TT/TagPage.pm
parentcf74837d76e2d5b00eb3dadda0b472c4b3114ce4 (diff)
v2rw/TagPage: Add /experimental/ tag page rewrite with AdvSearch support
Diffstat (limited to 'lib/VNWeb/TT/TagPage.pm')
-rw-r--r--lib/VNWeb/TT/TagPage.pm185
1 files changed, 185 insertions, 0 deletions
diff --git a/lib/VNWeb/TT/TagPage.pm b/lib/VNWeb/TT/TagPage.pm
new file mode 100644
index 00000000..80b14d8d
--- /dev/null
+++ b/lib/VNWeb/TT/TagPage.pm
@@ -0,0 +1,185 @@
+package VNWeb::TT::TagPage;
+
+use VNWeb::Prelude;
+use VNWeb::Filters;
+use VNWeb::AdvSearch;
+use VNWeb::VN::List;
+use VNWeb::TT::Lib 'tree_';
+
+
+sub parents_ {
+ my($t) = @_;
+
+ my %t;
+ push $t{$_->{child}}->@*, $_ for tuwf->dbAlli('
+ WITH RECURSIVE p(id,child,name) AS (
+ SELECT ', \$t->{id}, '::int, 0, NULL::text
+ UNION
+ SELECT t.id, p.id, t.name FROM p JOIN tags_parents tp ON tp.tag = p.id JOIN tags t ON t.id = tp.parent
+ ) SELECT * FROM p WHERE child <> 0 ORDER BY name
+ ')->@*;
+
+ my sub rec {
+ $t{$_[0]} ? map { my $e=$_; map [ @$_, $e ], __SUB__->($e->{id}) } $t{$_[0]}->@* : []
+ }
+
+ p_ sub {
+ join_ \&br_, sub {
+ a_ href => '/g', 'Tags';
+ for (@$_) {
+ txt_ ' > ';
+ a_ href => "/g$_->{id}", $_->{name};
+ }
+ txt_ ' > ';
+ txt_ $t->{name};
+ }, rec($t->{id});
+ };
+}
+
+
+sub infobox_ {
+ my($t) = @_;
+
+ p_ class => 'mainopts', sub {
+ a_ href => "/g$t->{id}/add", 'Create child tag';
+ } if $t->{state} != 1 && can_edit g => {};
+ h1_ "Tag: $t->{name}";
+ debug_ $t;
+
+ div_ class => 'warning', sub {
+ h2_ 'Tag deleted';
+ p_ sub {
+ txt_ 'This tag has been removed from the database, and cannot be used or re-added.';
+ br_;
+ txt_ 'File a request on the ';
+ a_ href => '/t/db', 'discussion board';
+ txt_ ' if you disagree with this.';
+ }
+ } if $t->{state} == 1;
+
+ div_ class => 'notice', sub {
+ h2_ 'Waiting for approval';
+ p_ 'This tag is waiting for a moderator to approve it. You can still use it to tag VNs as you would with a normal tag.';
+ } if $t->{state} == 0;
+
+ parents_ $t;
+
+ p_ class => 'description', sub {
+ lit_ bb_format $t->{description};
+ } if $t->{description};
+
+ my @prop = (
+ $t->{searchable} ? () : 'Not searchable.',
+ $t->{applicable} ? () : 'Can not be directly applied to visual novels.'
+ );
+ p_ class => 'center', sub {
+ b_ 'Properties';
+ br_;
+ join_ \&br_, \&txt_, @prop;
+ } if @prop;
+
+ p_ class => 'center', sub {
+ b_ 'Category';
+ br_;
+ txt_ $TAG_CATEGORY{$t->{cat}};
+ };
+
+ p_ class => 'center', sub {
+ b_ 'Aliases';
+ br_;
+ join_ \&br_, sub { txt_ $_ }, $t->{aliases}->@*;
+ } if $t->{aliases}->@*;
+}
+
+
+sub vns_ {
+ my($t) = @_;
+
+ my $opt = tuwf->validate(get =>
+ p => { upage => 1 },
+ f => { advsearch => 'v' },
+ s => { onerror => 'tagscore', enum => [qw/tagscore title rel pop rating/] },
+ o => { onerror => 'd', enum => ['a','d'] },
+ m => { onerror => [auth->pref('spoilers')||0], type => 'array', scalar => 1, minlength => 1, values => { enum => [0..2] } },
+ fil => { required => 0 },
+ )->data;
+ $opt->{m} = $opt->{m}[0];
+
+ # URL compatibility with old filters
+ if(!$opt->{f}->{query} && $opt->{fil}) {
+ my $q = eval {
+ tuwf->compile({ advsearch => 'v' })->validate(filter_release_adv filter_parse v => $opt->{fil})->data;
+ };
+ if(!$q) {
+ warn "Filter compatibility conversion failed\n$@";
+ } else {
+ return tuwf->resRedirect(tuwf->reqPath().'?'.query_encode(%$opt, fil => undef, f => $q), 'temp');
+ }
+ }
+
+ if(auth && !$opt->{f}{query} && !defined tuwf->reqGet('f')) {
+ my $def = tuwf->dbVali('SELECT query FROM saved_queries WHERE qtype = \'v\' AND name = \'\' AND uid =', \auth->uid);
+ $opt->{f} = tuwf->compile({ advsearch => 'v' })->validate($def)->data if $def;
+ }
+
+ my $where = sql 'tvi.tag =', \$t->{id}, 'AND NOT v.hidden AND tvi.spoiler <=', \$opt->{m}, 'AND', $opt->{f}->sql_where();
+
+ my $time = time;
+ my($count, $list);
+ db_maytimeout {
+ $count = tuwf->dbVali('SELECT count(*) FROM vn v JOIN tags_vn_inherit tvi ON tvi.vid = v.id WHERE', $where);
+ $list = $count ? tuwf->dbPagei({results => 50, page => $opt->{p}}, '
+ SELECT tvi.rating AS tagscore, v.id, v.title, v.original, v.c_released, v.c_popularity, v.c_votecount, v.c_rating
+ , v.c_platforms::text[] AS platforms, v.c_languages::text[] AS lang
+ FROM vn v
+ JOIN tags_vn_inherit tvi ON tvi.vid = v.id
+ WHERE', $where, '
+ ORDER BY', sprintf {
+ tagscore => 'tvi.rating %s, v.title',
+ title => 'v.title %s',
+ rel => 'v.c_released %s, v.title',
+ pop => 'v.c_popularity %s NULLS LAST, v.title',
+ rating => 'v.c_rating %s NULLS LAST, v.title'
+ }->{$opt->{s}}, $opt->{o} eq 'a' ? 'ASC' : 'DESC'
+ ) : [];
+ } || (($count, $list) = (undef, []));
+
+ VNWeb::VN::List::enrich_userlist $list;
+ $time = time - $time;
+
+ div_ class => 'mainbox', sub {
+ p_ class => 'mainopts', sub {
+ a_ href => "/g/links?t=$t->{id}", 'Recently tagged';
+ };
+ h1_ 'Visual novels';
+ form_ action => "/experimental/g$t->{id}", method => 'get', sub {
+ p_ class => 'browseopts', sub {
+ button_ type => 'submit', name => 'm', value => 0, $opt->{m} == 0 ? (class => 'optselected') : (), 'Hide spoilers';
+ button_ type => 'submit', name => 'm', value => 1, $opt->{m} == 1 ? (class => 'optselected') : (), 'Show minor spoilers';
+ button_ type => 'submit', name => 'm', value => 2, $opt->{m} == 2 ? (class => 'optselected') : (), 'Spoil me!';
+ };
+ input_ type => 'hidden', name => 'o', value => $opt->{o};
+ input_ type => 'hidden', name => 's', value => $opt->{s};
+ input_ type => 'hidden', name => 'm', value => $opt->{m};
+ $opt->{f}->elm_;
+ advsearch_msg_ $count, $time;
+ };
+ };
+ VNWeb::VN::List::listing_ $opt, $list, $count, 1 if $count;
+}
+
+
+TUWF::get qr{/experimental/$RE{gid}}, sub {
+ my $t = tuwf->dbRowi('SELECT id, name, description, state, c_items, cat, defaultspoil, searchable, applicable FROM tags WHERE id =', \tuwf->capture('id'));
+ return tuwf->resNotFound if !$t->{id};
+
+ enrich_flatten aliases => id => tag => sub { 'SELECT tag, alias FROM tags_aliases WHERE tag IN', $_, 'ORDER BY alias' }, $t;
+
+ framework_ index => $t->{state} == 2, title => "Tag: $t->{name}", type => 'g', dbobj => $t, sub {
+ div_ class => 'mainbox', sub { infobox_ $t; };
+ tree_ g => $t->{id};
+ vns_ $t if $t->{searchable} && $t->{state} == 2;
+ };
+};
+
+1;