summaryrefslogtreecommitdiff
path: root/lib/VNDB
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2015-11-11 15:51:40 +0100
committerYorhel <git@yorhel.nl>2015-11-11 16:00:34 +0100
commit1e97c0405a0cacb05d9d70429d7e7969e231b786 (patch)
tree1d31d74761726bf29868d1d0aebc66e188180dd9 /lib/VNDB
parentfd9f224ad7e1d6ebe4f7abba75526b5190c963ba (diff)
Misc poll improvements
- Merged polls table into threads table. Not much of a storage/performance difference, and it's a bit simpler this way. - Merged DB::Polls into DB::Discussions. Mainly because of the above change in DB structure. - Add option to remove an existing poll. - Allow preview and recast to be changed without deleting the votes - Set preview option by default. Because personal preferences. :) - Minor form validation differences
Diffstat (limited to 'lib/VNDB')
-rw-r--r--lib/VNDB/DB/Discussions.pm84
-rw-r--r--lib/VNDB/DB/Polls.pm95
-rw-r--r--lib/VNDB/Handler/Discussions.pm200
-rw-r--r--lib/VNDB/Util/FormHTML.pm4
4 files changed, 173 insertions, 210 deletions
diff --git a/lib/VNDB/DB/Discussions.pm b/lib/VNDB/DB/Discussions.pm
index c380feeb..b4771adc 100644
--- a/lib/VNDB/DB/Discussions.pm
+++ b/lib/VNDB/DB/Discussions.pm
@@ -5,11 +5,11 @@ use strict;
use warnings;
use Exporter 'import';
-our @EXPORT = qw|dbThreadGet dbThreadEdit dbThreadAdd dbPostGet dbPostEdit dbPostAdd dbThreadCount|;
+our @EXPORT = qw|dbThreadGet dbThreadEdit dbThreadAdd dbPostGet dbPostEdit dbPostAdd dbThreadCount dbPollStats dbPollVote|;
# Options: id, type, iid, results, page, what, notusers, search, sort, reverse
-# What: boards, boardtitles, firstpost, lastpost
+# What: boards, boardtitles, firstpost, lastpost, poll
# Sort: id lastpost
sub dbThreadGet {
my($self, %o) = @_;
@@ -38,9 +38,9 @@ sub dbThreadGet {
}
my @select = (
- qw|t.id t.title t.count t.locked t.hidden|,
+ qw|t.id t.title t.count t.locked t.hidden|, 't.poll_question IS NOT NULL AS haspoll',
$o{what} =~ /lastpost/ ? ('tpl.uid AS luid', q|EXTRACT('epoch' from tpl.date) AS ldate|, 'ul.username AS lusername') : (),
- 'p.id AS poll',
+ $o{what} =~ /poll/ ? (qw|t.poll_question t.poll_max_options t.poll_preview t.poll_recast|) : (),
);
my @join = (
@@ -50,7 +50,6 @@ sub dbThreadGet {
) : (),
$o{type} && $o{iid} ?
'JOIN threads_boards tb ON tb.tid = t.id' : (),
- 'LEFT JOIN polls p ON p.tid = t.id',
);
my $order = sprintf {
@@ -67,9 +66,10 @@ sub dbThreadGet {
join(', ', @select), join(' ', @join), \@where, $order
);
- if($o{what} =~ /(boards|boardtitles)/ && $#$r >= 0) {
+ if($o{what} =~ /(boards|boardtitles|poll)/ && $#$r >= 0) {
my %r = map {
$r->[$_]{boards} = [];
+ $r->[$_]{poll_options} = [];
($r->[$_]{id}, $_)
} 0..$#$r;
@@ -82,6 +82,15 @@ sub dbThreadGet {
)});
}
+ if($o{what} =~ /poll/) {
+ push(@{$r->[$r{$_->{tid}}]{poll_options}}, [ $_->{id}, $_->{option} ]) for (@{$self->dbAll(q|
+ SELECT tid, id, option
+ FROM threads_poll_options
+ WHERE tid IN(!l)|,
+ [ keys %r ]
+ )});
+ }
+
if($o{what} =~ /firstpost/) {
do { my $x = $r->[$r{$_->{tid}}]; $x->{fuid} = $_->{uid}; $x->{fdate} = $_->{date}; $x->{fusername} = $_->{username} } for (@{$self->dbAll(q|
SELECT tpf.tid, tpf.uid, EXTRACT('epoch' from tpf.date) AS date, uf.username
@@ -109,7 +118,10 @@ sub dbThreadGet {
}
-# id, %options->( title locked hidden boards }
+# id, %options->( title locked hidden boards poll_question poll_max_options poll_preview poll_recast poll_options }
+# The poll_{question,options,max_options} fields should not be set when there
+# are no changes to the poll info. Either all or none of these fields should be
+# set.
sub dbThreadEdit {
my($self, $id, %o) = @_;
@@ -117,6 +129,12 @@ sub dbThreadEdit {
'title = ?' => $o{title},
'locked = ?' => $o{locked}?1:0,
'hidden = ?' => $o{hidden}?1:0,
+ 'poll_preview = ?' => $o{poll_preview}?1:0,
+ 'poll_recast = ?' => $o{poll_recast}?1:0,
+ exists $o{poll_question} ? (
+ 'poll_question = ?' => $o{poll_question}||undef,
+ 'poll_max_options = ?' => $o{poll_max_options}||1,
+ ) : (),
);
$self->dbExec(q|
@@ -133,18 +151,27 @@ sub dbThreadEdit {
$id, $_->[0], $_->[1]||0
) for (@{$o{boards}});
}
+
+ if(exists $o{poll_question}) {
+ $self->dbExec('DELETE FROM threads_poll_options WHERE tid = ?', $id);
+ $self->dbExec(q|
+ INSERT INTO threads_poll_options (tid, option)
+ VALUES (?, ?)|,
+ $id, $_
+ ) for (@{$o{poll_options}});
+ }
}
-# %options->{ title hidden locked boards }
+# %options->{ title hidden locked boards poll_stuff }
sub dbThreadAdd {
my($self, %o) = @_;
my $id = $self->dbRow(q|
- INSERT INTO threads (title, hidden, locked)
- VALUES (?, ?, ?)
+ INSERT INTO threads (title, hidden, locked, poll_question, poll_max_options, poll_preview, poll_recast)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
RETURNING id|,
- $o{title}, $o{hidden}?1:0, $o{locked}?1:0
+ $o{title}, $o{hidden}?1:0, $o{locked}?1:0, $o{poll_question}||undef, $o{poll_max_options}||1, $o{poll_preview}?1:0, $o{poll_recast}?1:0
)->{id};
$self->dbExec(q|
@@ -153,6 +180,12 @@ sub dbThreadAdd {
$id, $_->[0], $_->[1]||0
) for (@{$o{boards}});
+ $self->dbExec(q|
+ INSERT INTO threads_poll_options (tid, option)
+ VALUES (?, ?)|,
+ $id, $_
+ ) for ($o{poll_question} ? @{$o{poll_options}} : ());
+
return $id;
}
@@ -287,5 +320,32 @@ sub dbPostAdd {
}
-1;
+# Args: tid
+# Returns: num_users, poll_stats, user_voted_options
+sub dbPollStats {
+ my($self, $tid) = @_;
+ my $uid = $self->authInfo->{id};
+
+ my $num_users = $self->dbRow('SELECT COUNT(DISTINCT uid) AS votes FROM threads_poll_votes WHERE tid = ?', $tid)->{votes} || 0;
+
+ my $stats = !$num_users ? {} : { map +($_->{optid}, $_->{votes}), @{$self->dbAll(
+ 'SELECT optid, COUNT(optid) AS votes FROM threads_poll_votes WHERE tid = ? GROUP BY optid', $tid
+ )} };
+
+ my $user = !$num_users || !$uid ? [] : [
+ map $_->{optid}, @{$self->dbAll('SELECT optid FROM threads_poll_votes WHERE tid = ? AND uid = ?', $tid, $uid)}
+ ];
+
+ return $num_users, $stats, $user;
+}
+
+sub dbPollVote {
+ my($self, $tid, $uid, @opts) = @_;
+
+ $self->dbExec('DELETE FROM threads_poll_votes WHERE tid = ? AND uid = ?', $tid, $uid);
+ $self->dbExec('INSERT INTO threads_poll_votes (tid, uid, optid) VALUES (?, ?, ?)',
+ $tid, $uid, $_) for @opts;
+}
+
+1;
diff --git a/lib/VNDB/DB/Polls.pm b/lib/VNDB/DB/Polls.pm
deleted file mode 100644
index 0b8ff81d..00000000
--- a/lib/VNDB/DB/Polls.pm
+++ /dev/null
@@ -1,95 +0,0 @@
-
-package VNDB::DB::Polls;
-
-use strict;
-use warnings;
-use Exporter 'import';
-
-our @EXPORT = qw|dbPollGet dbPollVote dbPollAdd dbPollEdit|;
-
-
-# Options: id, tid, uid, what
-# What: votes
-sub dbPollGet {
- my($self, %o) = @_;
- $o{what} ||= '';
- $o{uid} ||= $self->authInfo->{id};
-
- my %where = (
- $o{id} ? ('p.id = ?' => $o{id}) :
- $o{tid} ? ('p.tid = ?' => $o{tid}) : (),
- );
-
- my @select = (
- qw|p.id p.question p.max_options p.preview p.recast|,
- $o{what} =~ /votes/ ?
- ('(SELECT COUNT(DISTINCT uid) FROM polls_votes pv WHERE pv.pid = p.id) AS votes') : (),
- );
- my $p = $self->dbRow(q|
- SELECT !s
- FROM polls p
- !W|,
- join(', ', @select), \%where
- );
- return $p unless %$p;
-
- my $options_query = $o{what} =~ /votes/ ?
- q|SELECT id, option, COUNT(pv.optid) AS votes
- FROM polls_options po
- LEFT JOIN polls_votes pv ON po.id = pv.optid
- WHERE po.pid = ? GROUP BY id ORDER BY id| :
- q|SELECT id, option
- FROM polls_options po
- WHERE po.pid = ? ORDER BY id|;
- $p->{options} = $self->dbAll($options_query, $p->{id});
-
- $p->{user} = $o{uid} ? [
- map $_->{optid}, @{$self->dbAll(q|
- SELECT optid FROM polls_votes
- WHERE pid = ? AND uid = ?|, $p->{id}, $o{uid})}
- ] : [];
-
- return $p;
-}
-
-
-sub dbPollVote {
- my($self, $id, %o) = @_;
-
- $self->dbExec('DELETE FROM polls_votes WHERE pid = ? AND uid = ?', $id, $o{uid});
- $self->dbExec('INSERT INTO polls_votes (pid, uid, optid) VALUES (?, ?, ?)',
- $id, $o{uid}, $_) for @{$o{options}};
-}
-
-
-sub dbPollAdd {
- my($self, %o) = @_;
-
- my $id = $self->dbRow(q|
- INSERT INTO polls (tid, question, max_options, preview, recast)
- VALUES (?, ?, ?, ?, ?) RETURNING id|,
- $o{tid}, $o{question}, $o{max_options}, $o{preview}, $o{recast}
- )->{id};
-
- $self->dbExec('INSERT INTO polls_options (pid, option) VALUES (?, ?)', $id, $_)
- for @{$o{options}};
-
- return $id;
-}
-
-
-sub dbPollEdit {
- my($self, $id, %o) = @_;
-
- my %set = map exists $o{$_} ? ("$_ = ?" => $o{$_}) : (),
- qw|question max_options preview recast|;
-
- $self->dbExec('UPDATE polls !H WHERE id = ?', \%set, $id);
- $self->dbExec('DELETE FROM polls_options WHERE pid = ?', $id);
- $self->dbExec('INSERT INTO polls_options (pid, option) VALUES (?, ?)', $id, $_)
- for @{$o{options}};
-}
-
-
-1;
-
diff --git a/lib/VNDB/Handler/Discussions.pm b/lib/VNDB/Handler/Discussions.pm
index 4542a5fb..ae86010d 100644
--- a/lib/VNDB/Handler/Discussions.pm
+++ b/lib/VNDB/Handler/Discussions.pm
@@ -33,14 +33,12 @@ sub thread {
my($self, $tid, $page) = @_;
$page ||= 1;
- my $t = $self->dbThreadGet(id => $tid, what => 'boardtitles')->[0];
+ my $t = $self->dbThreadGet(id => $tid, what => 'boardtitles poll')->[0];
return $self->resNotFound if !$t->{id} || $t->{hidden} && !$self->authCan('boardmod');
my $p = $self->dbPostGet(tid => $tid, results => 25, page => $page, what => 'user');
return $self->resNotFound if !$p->[0];
- my $poll = $self->dbPollGet(id => $t->{poll}, what => 'votes') if $t->{poll};
-
$self->htmlHeader(title => $t->{title}, noindex => 1);
div class => 'mainbox';
h1 $t->{title};
@@ -60,7 +58,7 @@ sub thread {
end;
end 'div';
- _poll($self, "/t$tid".($page > 1 ? "/$page" : ''), $poll) if $poll;
+ _poll($self, $t, "/t$tid".($page > 1 ? "/$page" : '')) if $t->{haspoll};
$self->htmlBrowseNavigate("/t$tid/", $page, [ $t->{count}, 25 ], 't', 1);
div class => 'mainbox thread';
@@ -154,14 +152,12 @@ sub edit {
}
# get thread and post, if any
- my $t = $tid && $self->dbThreadGet(id => $tid, what => 'boards')->[0];
+ my $t = $tid && $self->dbThreadGet(id => $tid, what => 'boards poll')->[0];
return $self->resNotFound if $tid && !$t->{id};
my $p = $num && $self->dbPostGet(tid => $tid, num => $num, what => 'user')->[0];
return $self->resNotFound if $num && !$p->{num};
- $t->{poll} = $self->dbPollGet(id => $t->{poll}) if $tid && $t->{poll};
-
# are we allowed to perform this action?
return $self->htmlDenied if !$self->authCan('board')
|| ($tid && ($t->{locked} || $t->{hidden}) && !$self->authCan('boardmod'))
@@ -171,15 +167,19 @@ sub edit {
my $frm;
if($self->reqMethod eq 'POST') {
return if !$self->authCheckCode;
+ my $haspoll = $self->reqPost('poll') && 1;
$frm = $self->formValidate(
!$tid || $num == 1 ? (
{ post => 'title', maxlength => 50 },
{ post => 'boards', maxlength => 50 },
- { post => 'poll_q', required => 0, maxlength => 100 },
- { post => 'poll_opt', required => 0, maxlength => 100*$self->{poll_options} },
- { post => 'poll_max', required => 0, default => 1, template => 'uint', min => 1, max => $self->{poll_options} },
- { post => 'poll_preview', required => 0 },
- { post => 'poll_recast', required => 0 },
+ $haspoll ? (
+ { post => 'poll', required => 0 },
+ { post => 'poll_question', required => 1, maxlength => 100 },
+ { post => 'poll_options', required => 1, maxlength => 100*$self->{poll_options} },
+ { post => 'poll_max_options', required => 1, default => 1, template => 'uint', min => 1, max => $self->{poll_options} },
+ { post => 'poll_preview', required => 0 },
+ { post => 'poll_recast', required => 0 },
+ ) : (),
) : (),
$self->authCan('boardmod') ? (
{ post => 'locked', required => 0 },
@@ -219,19 +219,12 @@ sub edit {
}
# validate poll options
- my %poll;
- if(!$frm->{_err} && $frm->{poll_opt}) {
- # split by lines, trimming whitespace
- my @options = split /\s*\n\s*/, $frm->{poll_opt};
- %poll = (
- question => $frm->{poll_q},
- preview => $frm->{poll_preview}?1:0,
- recast => $frm->{poll_recast}?1:0,
- options => \@options,
- max_options => $frm->{poll_max},
- );
- push @{$frm->{_err}}, [ 'poll_max', 'max', scalar @options ] if @options > 1 && @options < $poll{max_options};
- push @{$frm->{_err}}, 'poll' if @options > $self->{poll_options} || @options < 2;
+ my @poll_options;
+ if(!$frm->{_err} && $haspoll) {
+ @poll_options = split /\s*\n\s*/, $frm->{poll_options};
+ push @{$frm->{_err}}, [ 'poll_options', 'mincount', 2 ] if @poll_options < 2;
+ push @{$frm->{_err}}, [ 'poll_options', 'maxcount', $frm->{poll_max_options} ] if @poll_options > $self->{poll_options};
+ push @{$frm->{_err}}, [ 'poll_max_options', 'template', 'uint' ] if @poll_options > 1 && @poll_options < $frm->{poll_max_options};
}
if(!$frm->{_err}) {
@@ -239,24 +232,28 @@ sub edit {
# create/edit thread
if(!$tid || $num == 1) {
+ my $pollchange = $haspoll && (!$t
+ || ($t->{poll_question}||'') ne $frm->{poll_question}
+ || $t->{poll_max_options} != $frm->{poll_max_options}
+ || join("\n", map $_->[1], @{$t->{poll_options}}) ne join("\n", @poll_options)
+ );
my %thread = (
title => $frm->{title},
boards => \@boards,
hidden => $frm->{hidden},
locked => $frm->{locked},
+ poll_preview => $frm->{poll_preview}||0,
+ poll_recast => $frm->{poll_recast}||0,
+ !$haspoll ? (
+ poll_question => undef # Make sure any existing poll gets deleted
+ ) : $pollchange ? (
+ poll_question => $frm->{poll_question},
+ poll_max_options => $frm->{poll_max_options},
+ poll_options => \@poll_options
+ ) : (),
);
$self->dbThreadEdit($tid, %thread) if $tid;
$ntid = $self->dbThreadAdd(%thread) if !$tid;
- if(%poll) {
- $poll{tid} = $ntid;
- if($tid && $t->{poll}) {
- my $same = (!first { !($t->{poll}{$_} ~~ $poll{$_}) } qw|question preview recast max_options|)
- && [ map $_->{option}, @{$t->{poll}{options}} ] ~~ $poll{options};
- $self->dbPollEdit($t->{poll}{id}, %poll) unless $same;
- } else {
- $self->dbPollAdd(%poll);
- }
- }
}
# create/edit post
@@ -279,20 +276,22 @@ sub edit {
if($num == 1) {
$frm->{boards} ||= join ' ', sort map $_->[1]?$_->[0].$_->[1]:$_->[0], @{$t->{boards}};
$frm->{title} ||= $t->{title};
- $frm->{locked} = $t->{locked} if !exists $frm->{locked};
- $frm->{hidden} = $t->{hidden} if !exists $frm->{hidden};
- if($t->{poll}) {
- $frm->{poll_q} ||= $t->{poll}{question};
- $frm->{poll_max} ||= $t->{poll}{max_options};
- $frm->{poll_preview} = $t->{poll}{preview} if !exists $frm->{poll_preview};
- $frm->{poll_recast} = $t->{poll}{recast} if !exists $frm->{poll_recast};
- $frm->{poll_opt} ||= join "\n", map $_->{option}, @{$t->{poll}{options}};
+ $frm->{locked} //= $t->{locked};
+ $frm->{hidden} //= $t->{hidden};
+ if($t->{haspoll}) {
+ $frm->{poll} //= 1;
+ $frm->{poll_question} ||= $t->{poll_question};
+ $frm->{poll_max_options} ||= $t->{poll_max_options};
+ $frm->{poll_preview} //= $t->{poll_preview};
+ $frm->{poll_recast} //= $t->{poll_recast};
+ $frm->{poll_options} ||= join "\n", map $_->[1], @{$t->{poll_options}};
}
}
}
delete $frm->{_err} unless ref $frm->{_err};
$frm->{boards} ||= $board;
- $frm->{poll_max} ||= 1;
+ $frm->{poll_preview} //= 1;
+ $frm->{poll_max_options} ||= 1;
# generate html
my $url = !$tid ? "/t/$board/new" : !$num ? "/t$tid/reply" : "/t$tid.$num/edit";
@@ -321,17 +320,16 @@ sub edit {
[ text => name => mt('_postedit_form_msg').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'msg', rows => 25, cols => 75 ],
[ static => content => mt('_postedit_form_msg_format') ],
(!$tid || $num == 1) ? (
- [ input => short => 'poll_q', name => mt('_postedit_form_poll_q'), width => 250 ],
- $num && $frm->{poll_opt} ? (
+ [ static => content => '<br />' ],
+ [ check => short => 'poll', name => mt('_postedit_form_poll_add') ],
+ $num && $frm->{poll_question} ? (
[ static => content => '<b class="standout">'.mt('_postedit_form_poll_warning').'</b>' ]
) : (),
- [ text => short => 'poll_opt', name => mt('_postedit_form_poll_opt').'<br /><i>'.mt('_postedit_form_poll_optmax', $self->{poll_options}).'</i>', rows => 8, cols => 35 ],
- [ input => short => 'poll_max', width => 16, post => ' '.mt('_postedit_form_poll_max') ],
+ [ input => short => 'poll_question', name => mt('_postedit_form_poll_q'), width => 250 ],
+ [ text => short => 'poll_options', name => mt('_postedit_form_poll_opt').'<br /><i>'.mt('_postedit_form_poll_optmax', $self->{poll_options}).'</i>', rows => 8, cols => 35 ],
+ [ input => short => 'poll_max_options',width => 16, post => ' '.mt('_postedit_form_poll_max') ],
[ check => short => 'poll_preview', name => mt('_postedit_form_poll_view') ],
[ check => short => 'poll_recast', name => mt('_postedit_form_poll_recast') ],
- !$frm->{poll_opt} ? (
- [ static => content => '<br /><a id="poll_add" class="hidden" href="#poll_q">'.mt('_postedit_form_poll_add').'</a>' ]
- ) : (),
) : (),
]);
$self->htmlFooter;
@@ -344,18 +342,16 @@ sub vote {
return if !$self->authCheckCode;
my $url = '/t'.$tid.($page ? "/$page" : '');
- my $poll = $self->dbPollGet(tid => $tid);
- return $self->resNotFound if !%$poll;
+ my $t = $self->dbThreadGet(id => $tid, what => 'poll')->[0];
+ return $self->resNotFound if !$t;
# user has already voted and poll doesn't allow to change a vote.
- return $self->resRedirect($url, 'post') if @{$poll->{user}} && !$poll->{recast};
+ my $voted = ($self->dbPollStats($tid))[2][0];
+ return $self->resRedirect($url, 'post') if $voted && !$t->{poll_recast};
- my $f = $self->formValidate({
- post => 'option', multi => 1, enum => [ map $_->{id}, @{$poll->{options}} ],
- });
- if(!$f->{_err} && (!@{$f->{option}} || @{$f->{option}} > $poll->{max_options})) {
- push @{$f->{_err}}, 'poll';
- }
+ my $f = $self->formValidate(
+ { post => 'option', multi => 1, mincount => 1, maxcount => $t->{poll_max_options}, enum => [ map $_->[0], @{$t->{poll_options}} ] }
+ );
if($f->{_err}) {
$self->htmlHeader(title => mt '_poll_error');
$self->htmlFormError($f, 1);
@@ -363,7 +359,7 @@ sub vote {
return;
}
- $self->dbPollVote($poll->{id}, uid => $self->authInfo->{id}, options => $f->{option});
+ $self->dbPollVote($t->{id}, $self->authInfo->{id}, @{$f->{option}});
$self->resRedirect($url, 'post');
}
@@ -601,7 +597,7 @@ sub _threadlist {
Tr;
td class => 'tc1';
a $o->{locked} ? ( class => 'locked' ) : (), href => "/t$o->{id}";
- span class => 'pollflag', '['.mt('_threadlist_poll').']' if $o->{poll};
+ span class => 'pollflag', '['.mt('_threadlist_poll').']' if $o->{haspoll};
txt shorten $o->{title}, 50;
end;
b class => 'boards';
@@ -635,59 +631,61 @@ sub _threadlist {
sub _poll {
- my($self, $url, $poll) = @_;
- my %own_votes = map +($_ => 1), @{$poll->{user}} if @{$poll->{user}};
- my $preview = !%own_votes && $self->reqGet('pollview') && $poll->{preview};
+ my($self, $t, $url) = @_;
+ my($num_votes, $stats, $own_votes) = $self->dbPollStats($t->{id});
+ my %own_votes = map +($_ => 1), @$own_votes;
+ my $preview = !@$own_votes && $self->reqGet('pollview') && $t->{poll_preview};
+ my $allow_vote = $self->authCan('board') && (!@$own_votes || $t->{poll_recast});
div class => 'mainbox poll';
form action => $url.'/vote', method => 'post';
- h1 class => 'question', $poll->{question} if $poll->{question};
- input type => 'hidden', name => 'formcode', value => $self->authGetCode($url.'/vote');
+ h1 class => 'question', $t->{poll_question};
+ input type => 'hidden', name => 'formcode', value => $self->authGetCode($url.'/vote') if $allow_vote;
table class => 'votebooth';
- my $allow_vote = $self->authCan('board') && (!%own_votes || $poll->{recast});
- if($allow_vote && $poll->{max_options} > 1) {
- thead; Tr; td colspan => 3;
- i mt('_poll_choose', $poll->{max_options});
- end; end; end;
- }
- tfoot; Tr;
- td class => 'tc1';
- input type => 'submit', class => 'submit', value => mt('_poll_vote') if $allow_vote;
- if(!$self->authCan('board')) {
- b class => 'standout', mt('_poll_novote_login');
- }
- end;
- td class => 'tc2', colspan => 2;
- if($poll->{preview} || %own_votes) {
- if(!$poll->{votes}) {
- i mt('_poll_no_votes');
- } elsif(!$preview && !%own_votes) {
- a href => $url.'?pollview=1', id => 'pollpreview', mt('_poll_results');
- } else {
- txt mt('_poll_total_votes', $poll->{votes});
- }
- }
- end;
- end; end;
+ if($allow_vote && $t->{poll_max_options} > 1) {
+ thead; Tr; td colspan => 3;
+ i mt('_poll_choose', $t->{poll_max_options});
+ end; end; end;
+ }
+ tfoot; Tr;
+ td class => 'tc1';
+ input type => 'submit', class => 'submit', value => mt('_poll_vote') if $allow_vote;
+ if(!$self->authCan('board')) {
+ b class => 'standout', mt('_poll_novote_login');
+ }
+ end;
+ td class => 'tc2', colspan => 2;
+ if($t->{poll_preview} || @$own_votes) {
+ if(!$num_votes) {
+ i mt('_poll_no_votes');
+ } elsif(!$preview && !@$own_votes) {
+ a href => $url.'?pollview=1', id => 'pollpreview', mt('_poll_results');
+ } else {
+ txt mt('_poll_total_votes', $num_votes);
+ }
+ }
+ end;
+ end; end;
tbody;
- my $max = max map $_->{votes}, @{$poll->{options}};
- my $show_graph = $max && (%own_votes || $preview);
+ my $max = max values %$stats;
+ my $show_graph = $max && (@$own_votes || $preview);
my $graph_width = 200;
- for my $opt (@{$poll->{options}}) {
- my $own = exists $own_votes{$opt->{id}} ? ' own' : '';
+ for my $opt (@{$t->{poll_options}}) {
+ my $votes = $stats->{$opt->[0]};
+ my $own = exists $own_votes{$opt->[0]} ? ' own' : '';
Tr $own ? (class => 'odd') : ();
td class => 'tc1';
label;
- input type => $poll->{max_options} > 1 ? 'checkbox' : 'radio', name => 'option', class => 'option', value => $opt->{id}, $own ? (checked => '') : () if $allow_vote;
- span class => 'option'.$own, $opt->{option};
+ input type => $t->{poll_max_options} > 1 ? 'checkbox' : 'radio', name => 'option', class => 'option', value => $opt->[0], $own ? (checked => '') : () if $allow_vote;
+ span class => 'option'.$own, $opt->[1];
end;
end;
if($show_graph) {
td class => 'tc2';
- div class => 'graph', style => sprintf('width: %dpx', $opt->{votes}/$max*$graph_width), ' ';
- div class => 'number', $opt->{votes};
+ div class => 'graph', style => sprintf('width: %dpx', ($votes||0)/$max*$graph_width), ' ';
+ div class => 'number', $votes;
end;
- td class => 'tc3', sprintf('%.3g%%', $poll->{votes} ? $opt->{votes}/$poll->{votes}*100 : 0);
+ td class => 'tc3', sprintf('%.3g%%', $votes ? $votes/$num_votes*100 : 0);
} else {
td class => 'tc2', colspan => 2, '';
}
diff --git a/lib/VNDB/Util/FormHTML.pm b/lib/VNDB/Util/FormHTML.pm
index e1f3bdfc..cca2b150 100644
--- a/lib/VNDB/Util/FormHTML.pm
+++ b/lib/VNDB/Util/FormHTML.pm
@@ -34,8 +34,8 @@ sub htmlFormError {
if($type eq 'required') {
li; lit mt $field eq 'editsum' ?'_formerr_tpl_editsum' : '_formerr_required', $field; end;
}
- li mt '_formerr_min', $field, $rule if $type eq 'min';
- li mt '_formerr_max', $field, $rule if $type eq 'max';
+ li mt '_formerr_mincount', $field, $rule if $type eq 'mincount';
+ li mt '_formerr_maxcount', $field, $rule if $type eq 'maxcount';
li mt '_formerr_minlength', $field, $rule if $type eq 'minlength';
li mt '_formerr_maxlength', $field, $rule if $type eq 'maxlength';
li mt '_formerr_enum', $field, join ', ', @$rule if $type eq 'enum';