summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2019-11-15 15:10:52 +0100
committerYorhel <git@yorhel.nl>2019-11-15 15:11:02 +0100
commit3306d14d9465f5a4d6a961bdca5c0db770c2ae1e (patch)
treefe08105c6c3e02daf042f62da7e62310da952d7b
parent3e100f4937a0af760bc73c6f2149f55e355705ee (diff)
v2rw: Convert discussion board index
Not super happy with the layout of the thread listing table, maybe I'll revisit that after converting the board listings. Also not super happy with the overall (lack of) structure in the board listing pages, should be able to find something for that as well.
-rw-r--r--lib/VNDB/Handler/Discussions.pm40
-rw-r--r--lib/VNWeb/Discussions/Index.pm36
-rw-r--r--lib/VNWeb/Discussions/Lib.pm87
-rw-r--r--lib/VNWeb/Discussions/Search.pm70
4 files changed, 130 insertions, 103 deletions
diff --git a/lib/VNDB/Handler/Discussions.pm b/lib/VNDB/Handler/Discussions.pm
index 82dcdfa1..add0e51c 100644
--- a/lib/VNDB/Handler/Discussions.pm
+++ b/lib/VNDB/Handler/Discussions.pm
@@ -3,7 +3,7 @@ package VNDB::Handler::Discussions;
use strict;
use warnings;
-use TUWF ':html', 'xml_escape', 'uri_escape';
+use TUWF ':html', 'xml_escape';
use POSIX 'ceil';
use VNDB::Func;
use VNDB::Types;
@@ -18,7 +18,6 @@ TUWF::register(
qr{t([1-9]\d*)/reply} => \&edit,
qr{t([1-9]\d*)\.([1-9]\d*)/edit} => \&edit,
qr{t/(db|an|ge|[vpu])([1-9]\d*)?/new} => \&edit,
- qr{t} => \&index,
);
@@ -449,43 +448,6 @@ sub board {
}
-sub index {
- my $self = shift;
-
- $self->htmlHeader(title => 'Discussion board index', noindex => 1, feeds => [ 'posts', 'announcements' ]);
- form action => '/t/search', method => 'get';
- div class => 'mainbox';
- h1 'Discussion board index';
- fieldset class => 'search';
- input type => 'text', name => 'bq', id => 'bq', class => 'text';
- input type => 'submit', class => 'submit', value => 'Search!';
- end 'fieldset';
- p class => 'browseopts';
- a href => '/t/all', 'All boards';
- a href => '/t/'.$_, $BOARD_TYPE{$_}{txt} for (keys %BOARD_TYPE);
- end;
- end;
- end;
-
- for (keys %BOARD_TYPE) {
- my $list = $self->dbThreadGet(
- type => $_,
- results => $BOARD_TYPE{$_}{index_rows},
- page => 1,
- what => 'firstpost lastpost boardtitles',
- sort => 'lastpost', reverse => 1,
- asuser => $self->authInfo()->{id},
- );
- h1 class => 'boxtitle';
- a href => "/t/$_", $BOARD_TYPE{$_}{txt};
- end;
- _threadlist($self, $list, {p=>1}, 0, "/t", $_);
- }
-
- $self->htmlFooter;
-}
-
-
sub _threadlist {
my($self, $list, $f, $np, $url, $board) = @_;
$self->htmlBrowse(
diff --git a/lib/VNWeb/Discussions/Index.pm b/lib/VNWeb/Discussions/Index.pm
new file mode 100644
index 00000000..4902c0e0
--- /dev/null
+++ b/lib/VNWeb/Discussions/Index.pm
@@ -0,0 +1,36 @@
+package VNWeb::Discussions::Index;
+
+use VNWeb::Prelude;
+use VNWeb::Discussions::Lib;
+
+
+TUWF::get qr{/t}, sub {
+ framework_ title => 'Discussion board index', sub {
+ form_ method => 'get', action => '/t/search', sub {
+ div_ class => 'mainbox', sub {
+ h1_ 'Discussion board index';
+ fieldset_ class => 'search', sub {
+ input_ type => 'text', name => 'bq', id => 'bq', class => 'text';
+ input_ type => 'submit', class => 'submit', value => 'Search!';
+ };
+ p_ class => 'browseopts', sub {
+ a_ href => '/t/all', 'All boards';
+ a_ href => '/t/'.$_, $BOARD_TYPE{$_}{txt} for (keys %BOARD_TYPE);
+ };
+ }
+ };
+
+ for my $b (keys %BOARD_TYPE) {
+ h1_ class => 'boxtitle', sub {
+ a_ href => "/t/$b", $BOARD_TYPE{$b}{txt};
+ };
+ threadlist_
+ where => sql('NOT t.private AND NOT t.hidden AND t.id IN(SELECT tid FROM threads_boards WHERE type =', \$b, ')'),
+ boards => sql('NOT (tb.type =', \$b, 'AND tb.iid = 0)'),
+ results => $BOARD_TYPE{$b}{index_rows},
+ page => 1;
+ }
+ }
+};
+
+1;
diff --git a/lib/VNWeb/Discussions/Lib.pm b/lib/VNWeb/Discussions/Lib.pm
new file mode 100644
index 00000000..c58c9020
--- /dev/null
+++ b/lib/VNWeb/Discussions/Lib.pm
@@ -0,0 +1,87 @@
+package VNWeb::Discussions::Lib;
+
+use VNWeb::Prelude;
+use Exporter 'import';
+
+our @EXPORT = qw/threadlist_/;
+
+
+# Generate a thread list table, options:
+# where => SQL for the WHERE clause ('t' is available as alias for 'threads').
+# boards => SQL for the WHERE clause of the boards ('tb' as alias for 'threads_boards').
+# results => Number of threads to display.
+# page => Current page number.
+# paginate => sub {} reference that generates a url for paginate_(); pagination is disabled when not set.
+#
+# Returns 1 if something was displayed, 0 if no threads matched the where clause.
+sub threadlist_ {
+ my %opt = @_;
+
+ my $count = $opt{paginate} && tuwf->dbVali('SELECT count(*) FROM threads t WHERE', $opt{where});
+ return 0 if $opt{paginate} && !$count;
+
+ my $lst = tuwf->dbPagei(\%opt, q{
+ SELECT t.id, t.title, t.count, t.locked, t.poll_question IS NOT NULL AS haspoll
+ , }, sql_user('tfu', 'firstpost_'), ',', sql_totime('tf.date'), q{ as firstpost_date
+ , }, sql_user('tlu', 'lastpost_'), ',', sql_totime('tl.date'), q{ as lastpost_date
+ FROM threads t
+ JOIN threads_posts tf ON tf.tid = t.id AND tf.num = 1
+ JOIN threads_posts tl ON tl.tid = t.id AND tl.num = t.count
+ JOIN users tfu ON tfu.id = tf.uid
+ JOIN users tlu ON tlu.id = tl.uid
+ WHERE }, $opt{where}, q{
+ ORDER BY tl.date DESC
+ });
+ return 0 if !@$lst;
+
+ enrich boards => id => tid => sub { sql q{
+ SELECT tb.tid, tb.type, tb.iid, COALESCE(u.username, v.title, p.name) AS title, COALESCE(u.username, v.original, p.original) AS original
+ FROM threads_boards tb
+ LEFT JOIN vn v ON tb.type = 'v' AND v.id = tb.iid
+ LEFT JOIN producers p ON tb.type = 'p' AND p.id = tb.iid
+ LEFT JOIN users u ON tb.type = 'u' AND u.id = tb.iid
+ WHERE }, sql_and(sql('tb.tid IN', $_[0]), $opt{boards}||()), q{
+ ORDER BY tb.type, tb.iid
+ }}, $lst;
+
+
+ paginate_ $opt{paginate}, $opt{page}, [ $count, $opt{results} ], 't' if $opt{paginate};
+ div_ class => 'mainbox browse discussions', sub {
+ table_ class => 'stripe', sub {
+ thead_ sub { tr_ sub {
+ td_ class => 'tc1', sub { txt_ 'Topic'; debug_ $lst };
+ td_ class => 'tc2', 'Replies';
+ td_ class => 'tc3', 'Starter';
+ td_ class => 'tc4', 'Last post';
+ }};
+ tr_ sub {
+ my $l = $_;
+ td_ class => 'tc1', sub {
+ a_ mkclass(locked => $l->{locked}), href => "/t$l->{id}", sub {
+ span_ class => 'pollflag', '[poll]' if $l->{haspoll};
+ txt_ shorten $l->{title}, 50;
+ };
+ b_ class => 'boards', sub {
+ join_ ', ', sub {
+ a_ href => "/t/$_->{type}".($_->{iid}||''),
+ title => $_->{original}||$BOARD_TYPE{$_->{type}}{txt},
+ shorten $_->{title}||$BOARD_TYPE{$_->{type}}{txt}, 30;
+ }, $l->{boards}->@[0 .. min 4, $#{$l->{boards}}];
+ txt_ ', ...' if $l->{boards}->@* > 4;
+ };
+ };
+ td_ class => 'tc2', $l->{count}-1;
+ td_ class => 'tc3', sub { user_ $l, 'firstpost_' };
+ td_ class => 'tc4', sub {
+ user_ $l, 'lastpost_';
+ txt_ ' @ ';
+ a_ href => "/t$l->{id}.$l->{count}", fmtdate $l->{lastpost_date}, 'full';
+ };
+ } for @$lst;
+ }
+ };
+ paginate_ $opt{paginate}, $opt{page}, [ $count, $opt{results} ], 'b' if $opt{paginate};
+ 1;
+}
+
+1;
diff --git a/lib/VNWeb/Discussions/Search.pm b/lib/VNWeb/Discussions/Search.pm
index 9c947337..3718bad7 100644
--- a/lib/VNWeb/Discussions/Search.pm
+++ b/lib/VNWeb/Discussions/Search.pm
@@ -1,6 +1,7 @@
package VNWeb::Discussions::Search;
use VNWeb::Prelude;
+use VNWeb::Discussions::Lib;
sub filters_ {
@@ -127,70 +128,11 @@ sub threads_ {
$filt->{b}->@* < keys %BOARD_TYPE ? sql('t.id IN(SELECT tid FROM threads_boards WHERE type IN', $filt->{b}, ')') : (),
map sql('t.title ilike', \('%'.($_ =~ s/%//gr).'%')), grep length($_) > 0, split /[ -,._]/, $filt->{bq};
- my $count = tuwf->dbVali('SELECT count(*) FROM threads t WHERE', $where);
- return noresults_ if !$count;
-
- my $lst = tuwf->dbPagei({ results => 50, page => $filt->{p} }, q{
- SELECT t.id, t.title, t.count, t.locked, t.poll_question IS NOT NULL AS haspoll
- , }, sql_user('tfu', 'firstpost_'), ',', sql_totime('tf.date'), q{ as firstpost_date
- , }, sql_user('tlu', 'lastpost_'), ',', sql_totime('tl.date'), q{ as lastpost_date
- FROM threads t
- JOIN threads_posts tf ON tf.tid = t.id AND tf.num = 1
- JOIN threads_posts tl ON tl.tid = t.id AND tl.num = t.count
- JOIN users tfu ON tfu.id = tf.uid
- JOIN users tlu ON tlu.id = tl.uid
- WHERE }, $where, q{
- ORDER BY tl.date DESC
- });
-
- enrich boards => id => tid => sub { sql q{
- SELECT tb.tid, tb.type, tb.iid, COALESCE(u.username, v.title, p.name) AS title, COALESCE(u.username, v.original, p.original) AS original
- FROM threads_boards tb
- LEFT JOIN vn v ON tb.type = 'v' AND v.id = tb.iid
- LEFT JOIN producers p ON tb.type = 'p' AND p.id = tb.iid
- LEFT JOIN users u ON tb.type = 'u' AND u.id = tb.iid
- WHERE tb.tid IN}, $_[0], q{
- ORDER BY tb.type, tb.iid
- }}, $lst;
-
-
- my sub url { '?'.query_encode %$filt, @_ }
- paginate_ \&url, $filt->{p}, [ $count, 50 ], 't';
- div_ class => 'mainbox browse discussions', sub {
- table_ class => 'stripe', sub {
- thead_ sub { tr_ sub {
- td_ class => 'tc1', sub { txt_ 'Topic'; debug_ $lst };
- td_ class => 'tc2', 'Replies';
- td_ class => 'tc3', 'Starter';
- td_ class => 'tc4', 'Last post';
- }};
- tr_ sub {
- my $l = $_;
- td_ class => 'tc1', sub {
- a_ mkclass(locked => $l->{locked}), href => "/t$l->{id}", sub {
- span_ class => 'pollflag', '[poll]' if $l->{haspoll};
- txt_ shorten $l->{title}, 50;
- };
- b_ class => 'boards', sub {
- join_ ', ', sub {
- a_ href => "/t/$_->{type}".($_->{iid}||''),
- title => $_->{original}||$BOARD_TYPE{$_->{type}}{txt},
- shorten $_->{title}||$BOARD_TYPE{$_->{type}}{txt}, 30;
- }, $l->{boards}->@[0 .. min 4, $#{$l->{boards}}];
- txt_ ', ...' if $l->{boards}->@* > 4;
- };
- };
- td_ class => 'tc2', $l->{count}-1;
- td_ class => 'tc3', sub { user_ $l, 'firstpost_' };
- td_ class => 'tc4', sub {
- user_ $l, 'lastpost_';
- txt_ ' @ ';
- a_ href => "/t$l->{id}.$l->{count}", fmtdate $l->{lastpost_date}, 'full';
- };
- } for @$lst;
- }
- };
- paginate_ \&url, $filt->{p}, [ $count, 50 ], 'b';
+ noresults_ if !threadlist_
+ where => $where,
+ results => 50,
+ page => $filt->{p},
+ paginate => sub { '?'.query_encode %$filt, @_ };
}