summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-08-05 12:44:22 +0200
committerYorhel <git@yorhel.nl>2020-08-07 12:36:58 +0200
commit33edaf611419a09391d5ed6eedee15416925f8e1 (patch)
treec5e0d87c8ee5c1b8656da671cff8f3c9fee8d13b
parent26279ce6283511ac67c00d1ce98eca56ce3e8e60 (diff)
reviews: Add page for individual reviews
-rw-r--r--data/style.css11
-rw-r--r--lib/VNWeb/Reviews/Page.pm97
-rw-r--r--lib/VNWeb/Reviews/VNTab.pm2
-rw-r--r--lib/VNWeb/VN/Page.pm6
4 files changed, 112 insertions, 4 deletions
diff --git a/data/style.css b/data/style.css
index 8f9d8ee2..d15391d6 100644
--- a/data/style.css
+++ b/data/style.css
@@ -614,6 +614,17 @@ div.producerbrowse { padding-bottom: 10px }
+/***** Review page *****/
+
+.fullreview td { padding: 0 0 15px 10px }
+.fullreview tr > td:first-child { width: 140px; text-align: right; font-weight: bold }
+.fullreview tr > td:last-child { max-width: 700px }
+.fullreview .myvote { font-weight: bold }
+
+#reviewspoil:not(:checked) ~ .fullreview .reviewspoil { display: none }
+#reviewspoil:checked ~ .fullreview .reviewnotspoil { display: none }
+
+
/***** Release browser *****/
.relbrowse .tc1 { width: 80px }
diff --git a/lib/VNWeb/Reviews/Page.pm b/lib/VNWeb/Reviews/Page.pm
new file mode 100644
index 00000000..3d379d10
--- /dev/null
+++ b/lib/VNWeb/Reviews/Page.pm
@@ -0,0 +1,97 @@
+package VNWeb::Reviews::Page;
+
+use VNWeb::Prelude;
+use VNWeb::Releases::Lib;
+
+
+sub review_ {
+ my($w) = @_;
+
+ input_ type => 'checkbox', class => 'visuallyhidden', id => 'reviewspoil', undef;
+ my @spoil = $w->{spoiler} ? (class => 'reviewspoil') : ();
+ table_ class => 'fullreview', sub {
+ tr_ sub {
+ td_ 'By';
+ td_ sub {
+ b_ style => 'float: right', 'Vote: '.fmtvote($w->{vote}) if $w->{vote};
+ user_ $w;
+ my($date, $lastmod) = map fmtdate($_,'compact'), $w->@{'date', 'lastmod'};
+ txt_ " on $date";
+ b_ class => 'grayedout', " last updated on $lastmod" if $date ne $lastmod;
+ }
+ };
+ tr_ sub {
+ td_ 'Release';
+ td_ sub {
+ abbr_ class => "icons $_", title => $PLATFORM{$_}, '' for grep $_ ne 'oth', $w->{platforms}->@*;
+ abbr_ class => "icons lang $_", title => $LANGUAGE{$_}, '' for $w->{lang}->@*;
+ abbr_ class => "icons rt$w->{rtype}", title => $w->{rtype}, '';
+ a_ href => "/r$w->{rid}", title => $w->{roriginal}||$w->{rtitle}, $w->{rtitle};
+ };
+ } if $w->{rid};
+ tr_ class => 'reviewnotspoil', sub {
+ td_ '';
+ td_ sub {
+ label_ class => 'fake_link', for => 'reviewspoil', 'This review contains spoilers, click to view.';
+ };
+ } if $w->{spoiler};
+ tr_ @spoil, sub {
+ td_ length $w->{text} ? 'Summary' : 'Review';
+ td_ sub { lit_ bb2html $w->{summary} }
+ };
+ tr_ @spoil, sub {
+ td_ 'Full review';
+ td_ sub { lit_ bb2html $w->{text} }
+ } if length $w->{text};
+ tr_ sub {
+ td_ '';
+ td_ style => 'text-align: right', sub {
+ elm_ 'Reviews.Vote' => $VNWeb::Reviews::Elm::VOTE_OUT, { %$w, can => !!auth }, sub {
+ span_ sprintf '๐Ÿ‘ %d ๐Ÿ‘Ž %d', $w->{up}, $w->{down};
+ };
+ }
+ };
+ }
+}
+
+
+TUWF::get qr{/$RE{wid}}, sub {
+ my $w = tuwf->dbRowi(
+ 'SELECT r.id, r.vid, r.rid, r.summary, r.text, r.spoiler, uv.vote
+ , rel.title AS rtitle, rel.original AS roriginal, rel.type AS rtype
+ , COALESCE(s.up,0) AS up, COALESCE(s.down,0) AS down, rv.vote AS my
+ , ', sql_user(), ',', sql_totime('r.date'), 'AS date,', sql_totime('r.lastmod'), 'AS lastmod
+ FROM reviews r
+ LEFT JOIN releases rel ON rel.id = r.rid
+ LEFT JOIN users u ON u.id = r.uid
+ LEFT JOIN ulist_vns uv ON uv.uid = r.uid AND uv.vid = r.vid
+ LEFT JOIN (SELECT id, COUNT(*) FILTER(WHERE vote), COUNT(*) FILTER(WHERE NOT vote) FROM reviews_votes GROUP BY id) AS s(id,up,down) ON s.id = r.id
+ LEFT JOIN reviews_votes rv ON rv.id = r.id AND rv.uid =', \auth->uid, '
+ WHERE r.id =', \tuwf->capture('id')
+ );
+ return tuwf->resNotFound if !$w->{id};
+
+ enrich_flatten lang => rid => id => sub { sql 'SELECT id, lang FROM releases_lang WHERE id IN', $_, 'ORDER BY id, lang' }, $w;
+ enrich_flatten platforms => rid => id => sub { sql 'SELECT id, platform FROM releases_platforms WHERE id IN', $_, 'ORDER BY id, platform' }, $w;
+
+ my $v = db_entry v => $w->{vid};
+ VNWeb::VN::Page::enrich_vn($v);
+
+ framework_ title => "Review of $v->{title}", index => 1, type => 'v', dbobj => $v, hiddenmsg => 1, sub {
+ VNWeb::VN::Page::infobox_($v);
+ VNWeb::VN::Page::tabs_($v, 'reviews');
+ div_ class => 'mainbox', sub {
+ p_ class => 'mainopts', sub {
+ if(can_edit w => $w) {
+ a_ href => "/$w->{id}/edit", 'Edit';
+ b_ class => 'grayedout', ' | ';
+ }
+ a_ href => "/report/w/$w->{id}", 'Report'; # TODO
+ };
+ h1_ "Review";
+ review_ $w;
+ };
+ };
+};
+
+1;
diff --git a/lib/VNWeb/Reviews/VNTab.pm b/lib/VNWeb/Reviews/VNTab.pm
index 52fd62a2..1f66b408 100644
--- a/lib/VNWeb/Reviews/VNTab.pm
+++ b/lib/VNWeb/Reviews/VNTab.pm
@@ -54,7 +54,7 @@ sub reviews_ {
};
div_ sub {
span_ '' if !$r->{isfull};
- a_ href => "/$r->{id}", 'Full review ยป' if $r->{isfull};
+ a_ href => "/$r->{id}#review", 'Full review ยป' if $r->{isfull};
elm_ 'Reviews.Vote' => $VNWeb::Reviews::Elm::VOTE_OUT, { %$r, can => !!auth }, sub {
span_ sprintf '๐Ÿ‘ %d ๐Ÿ‘Ž %d', $r->{up}, $r->{down};
};
diff --git a/lib/VNWeb/VN/Page.pm b/lib/VNWeb/VN/Page.pm
index b057230d..72526e38 100644
--- a/lib/VNWeb/VN/Page.pm
+++ b/lib/VNWeb/VN/Page.pm
@@ -8,7 +8,7 @@ use POSIX 'strftime';
# Enrich everything necessary to at least render infobox_().
-# Also used by Chars::VNTab & Reviews::VNTab
+# Also used by Chars::VNTab & Reviews::{Page,VNTab}
sub enrich_vn {
my($v) = @_;
enrich_merge id => 'SELECT id, c_votecount, c_olang::text[] AS c_olang FROM vn WHERE id IN', $v;
@@ -325,7 +325,7 @@ sub infobox_useroptions_ {
}
-# Also used by Chars::VNTab & Reviews::VNTab
+# Also used by Chars::VNTab & Reviews::{Page,VNTab}
sub infobox_ {
my($v) = @_;
div_ class => 'mainbox', sub {
@@ -383,7 +383,7 @@ sub infobox_ {
}
-# Also used by Chars::VNTab & Reviews::VNTab
+# Also used by Chars::VNTab & Reviews::{Page,VNTab}
sub tabs_ {
my($v, $tab) = @_;
# XXX: This query is kind of silly because we'll be fetching a list of characters regardless of which tab we have open.