summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-10-31 09:29:01 +0100
committerYorhel <git@yorhel.nl>2020-10-31 09:59:17 +0100
commit90e2dc96e786da59722b3a94dc74c2325776231d (patch)
treec68cb66bd2412110a548ef17e0a8cb1c2afce843
parentfea1149af17b784aed285d71c39b2ba2690d1cfe (diff)
Advsearch: Display results
Same browse UI as the old one. I hope to extend this UI with a lot more options, later on. But let's first focus on feature parity.
-rw-r--r--elm/AdvSearch/Main.elm3
-rw-r--r--lib/VNWeb/VN/List.pm73
2 files changed, 72 insertions, 4 deletions
diff --git a/elm/AdvSearch/Main.elm b/elm/AdvSearch/Main.elm
index 56352b6d..a86438fb 100644
--- a/elm/AdvSearch/Main.elm
+++ b/elm/AdvSearch/Main.elm
@@ -101,7 +101,4 @@ view model = div [ class "advsearch" ]
--, input [ type_ "button", class "submit", value "Advanced mode" ] [] -- TODO: Advanced mode where you can construct arbitrary queries.
[ input [ type_ "submit", class "submit", value "Search" ] []
]
- , pre []
- [ text <| Maybe.withDefault "" <| Maybe.map (\v -> JE.encode 2 (encodeQuery v)) (fqueryToQuery model.query)
- ]
]
diff --git a/lib/VNWeb/VN/List.pm b/lib/VNWeb/VN/List.pm
index a9cf6fb4..e968db55 100644
--- a/lib/VNWeb/VN/List.pm
+++ b/lib/VNWeb/VN/List.pm
@@ -4,11 +4,54 @@ use VNWeb::Prelude;
use VNWeb::AdvSearch;
+sub listing_ {
+ my($opt, $list, $count) = @_;
+
+ # TODO: query_encode() should recognize and encode the search query automatically.
+ $opt->{f} = JSON::XS->new->encode($opt->{f}) if $opt->{f};
+ my sub url { '?'.query_encode %$opt, @_ }
+
+ paginate_ \&url, $opt->{p}, [$count, 50], 't';
+ div_ class => 'mainbox browse vnbrowse', sub {
+ table_ class => 'stripe', sub {
+ thead_ sub { tr_ sub {
+ td_ class => 'tc1', sub { txt_ 'Title'; sortable_ 'title', $opt, \&url };
+ td_ class => 'tc7', '';
+ td_ class => 'tc2', '';
+ td_ class => 'tc3', '';
+ td_ class => 'tc4', sub { txt_ 'Released'; sortable_ 'rel', $opt, \&url };
+ td_ class => 'tc5', sub { txt_ 'Popularity'; sortable_ 'pop', $opt, \&url };
+ td_ class => 'tc6', sub { txt_ 'Rating'; sortable_ 'rating', $opt, \&url };
+ } };
+ tr_ sub {
+ td_ class => 'tc1', sub { a_ href => "/v$_->{id}", title => $_->{original}||$_->{title}, $_->{title} };
+ td_ class => 'tc7', sub {
+ b_ class => $_->{userlist_obtained} == $_->{userlist_all} ? 'done' : 'todo', sprintf '%d/%d', $_->{userlist_obtained}, $_->{userlist_all} if $_->{userlist_all};
+ abbr_ title => join(', ', $_->{vnlist_labels}->@*), scalar $_->{vnlist_labels}->@* if $_->{vnlist_labels} && $_->{vnlist_labels}->@*;
+ abbr_ title => 'No labels', ' ' if $_->{vnlist_labels} && !$_->{vnlist_labels}->@*;
+ };
+ td_ class => 'tc2', sub { join_ '', sub { abbr_ class => "icons $_", title => $PLATFORM{$_}, '' if $_ ne 'unk' }, sort $_->{platforms}->@* };
+ td_ class => 'tc3', sub { join_ '', sub { abbr_ class => "icons lang $_", title => $LANGUAGE{$_}, '' }, reverse sort $_->{lang}->@* };
+ td_ class => 'tc4', sub { rdate_ $_->{c_released} };
+ td_ class => 'tc5', sprintf '%.2f', ($_->{c_popularity}||0)*100;
+ td_ class => 'tc6', sub {
+ txt_ sprintf '%.2f', ($_->{c_rating}||0)/10;
+ b_ class => 'grayedout', sprintf ' (%d)', $_->{c_votecount};
+ };
+ } for @$list;
+ }
+ };
+ paginate_ \&url, $opt->{p}, [$count, 50], 'b';
+}
+
+
TUWF::get qr{/experimental/v}, sub {
my $opt = tuwf->validate(get =>
q => { onerror => '' },
p => { upage => 1 },
f => { advsearch => 'v' },
+ s => { onerror => 'title', enum => [qw/title rel pop rating/] },
+ o => { onerror => 'a', enum => ['a','d'] },
)->data;
my $where = sql_and
@@ -18,6 +61,33 @@ TUWF::get qr{/experimental/v}, sub {
my $time = time;
my $count = tuwf->dbVali('SELECT count(*) FROM vn v WHERE', $where);
+ my $list = $count && tuwf->dbPagei({results => 50, page => $opt->{p}}, '
+ SELECT 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
+ , vl.userlist_all, vl.userlist_obtained
+ FROM vn v
+ LEFT JOIN (
+ SELECT irv.vid, COUNT(*) AS userlist_all
+ , SUM(CASE WHEN irl.status = 1+1 THEN 1 ELSE 0 END) AS userlist_obtained
+ FROM rlists irl
+ JOIN releases_vn irv ON irv.id = irl.rid
+ WHERE irl.uid =', \auth->uid, '
+ GROUP BY irv.vid
+ ) AS vl ON vl.vid = v.id
+ WHERE', $where, '
+ ORDER BY', sprintf {
+ 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'
+ );
+ enrich_flatten vnlist_labels => id => vid => sub { sql '
+ SELECT uvl.vid, ul.label
+ FROM ulist_vns_labels uvl
+ JOIN ulist_labels ul ON ul.uid = uvl.uid AND ul.id = uvl.lbl
+ WHERE uvl.uid =', \auth->uid, 'AND uvl.vid IN', $_[0], '
+ ORDER BY CASE WHEN ul.id < 10 THEN ul.id ELSE 10 END, ul.label'
+ }, $list if $count && auth;
$time = time - $time;
framework_ title => 'Browse visual novels', sub {
@@ -32,8 +102,9 @@ TUWF::get qr{/experimental/v}, sub {
searchbox_ v => $opt->{q};
as_elm_ v => $opt->{f};
};
- p_ sprintf '%d results in %.3fs', $count, $time;
+ p_ class => 'center', sprintf '%d results in %.3fs', $count, $time;
};
+ listing_ $opt, $list, $count if $count;
};
};