summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2011-01-04 17:30:57 +0100
committerYorhel <git@yorhel.nl>2011-01-04 17:30:57 +0100
commitd5d55cb04e95fdf9d5185e9f8516e906eeb03831 (patch)
treece9b50520ac3533ace8021ff8149c630dc173a23
parenta48a7f5b0d4e65a70337d40f7df287810f27d547 (diff)
Added checkboxes to VN tagmod and implemented the overrule logic
This finalizes the moderation tag vote overrule. And Damnit, the logic behind saving the tags to the database isn't fun, I hope I haven't made any mistakes there.
-rw-r--r--ChangeLog1
-rw-r--r--data/script.js6
-rw-r--r--data/style.css1
-rw-r--r--lib/VNDB/DB/Tags.pm47
-rw-r--r--lib/VNDB/Handler/Tags.pm66
5 files changed, 84 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index a3c35c37..098ef3f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
- Bugfix: Don't show NSFW screenshots on homepage with filters
- Bugfix-API: Use ~ for the get vn search filter instead of =
- Bugfix: Secondary order by title or username on vote listings
+ - Allow moderators to overrule VN tag votes
2.16 - 2011-01-02
- VNDBUtil::bb2html(): Fixed bug when the string starts with a VNDBID
diff --git a/data/script.js b/data/script.js
index a946a4f3..ff571630 100644
--- a/data/script.js
+++ b/data/script.js
@@ -1344,9 +1344,13 @@ function tglAdd() {
ddInit(spoil, 'tagmod', tglSpoilDD);
spoil.onclick = tglSpoilNext;
+ var ismod = byClass(byId('tagtable').parentNode, 'td', 'tc_myover').length;
+
byId('tagtable').appendChild(tag('tr', {id:'tgl_'+id},
tag('td', {'class':'tc_tagname'}, tag('a', {href:'/g'+id}, name)),
- vote, spoil,
+ vote,
+ ismod ? tag('td', {'class':'tc_myover'}, ' ') : null,
+ spoil,
tag('td', {'class':'tc_allvote'}, ' '),
tag('td', {'class':'tc_allspoil'}, ' '),
tag('td', {'class':'tc_allwho'}, '')
diff --git a/data/style.css b/data/style.css
index 86967cc0..f64596c0 100644
--- a/data/style.css
+++ b/data/style.css
@@ -965,6 +965,7 @@ table.tgl .tc_you { border-right: 1px solid $border$; border-left: 1px solid $bo
table.tgl .tc_others { border-left: 1px solid $border$; width: 150px; text-align: center }
table.tgl .tc_tagname { min-width: 200px; border-right: 1px solid $border$ }
table.tgl .tc_myvote { padding-left: 30px!important }
+table.tgl .tc_myover { padding: 0!important }
table.tgl .tc_myspoil { border-right: 1px solid $border$; padding-right: 30px!important; text-align: right; padding-left: 10px!important; cursor: pointer }
table.tgl .tc_allvote { padding-left: 30px!important; }
table.tgl .tc_allvote i { font-style: normal; font-size: 8px }
diff --git a/lib/VNDB/DB/Tags.pm b/lib/VNDB/DB/Tags.pm
index 623ac10d..b7792eb8 100644
--- a/lib/VNDB/DB/Tags.pm
+++ b/lib/VNDB/DB/Tags.pm
@@ -202,36 +202,31 @@ sub dbTagLinks {
# Change a user's tags for a VN entry
-# Arguments: uid, vid, [ [ tag, vote, spoiler ], .. ]
sub dbTagLinkEdit {
- my($self, $uid, $vid, $new) = @_;
-
- # compare with the old votes and determine which to delete, and/or insert
- my %old = map +($_->{tag}, [ $_->{vote}, $_->{spoiler} // -1 ]),
- @{$self->dbTagLinks(vid => $vid, uid => $self->authInfo->{id})};
- my %new = map +($_->[0], [ $_->[1], $_->[2] ]), @$new;
-
- my(%delete, %update, %insert);
- for my $tag (keys %old, keys %new) {
- if($old{$tag} && !$new{$tag}) {
- $delete{$tag} = 1;
- } elsif(!$old{$tag} && $new{$tag}) {
- $insert{$tag} = $new{$tag};
- } elsif($old{$tag}[0] != $new{$tag}[0] || $old{$tag}[1] != $new{$tag}[1]) {
- $update{$tag} = $new{$tag};
- }
- }
+ my($self, $uid, $vid, $insert, $update, $delete, $overrule) = @_;
+
+ # overrule
+ # 1. set ignore flag for everyone except $uid
+ $self->dbExec('UPDATE tags_vn SET ignore = ? WHERE tag = ? AND vid = ? AND uid <> ?',
+ $overrule->{$_}?1:0, $_, $vid, $uid) for(keys %$overrule);
+ # 2. make sure $uid isn't ignored when others are set to ignore
+ # (this happens when a mod takes over an other mods' overrule)
+ $self->dbExec('UPDATE tags_vn SET ignore = false WHERE tag = ? AND vid = ? AND uid = ?',
+ $_, $vid, $uid) for(grep $overrule->{$_}, keys %$overrule);
+
+ # delete
+ $self->dbExec('DELETE FROM tags_vn WHERE vid = ? AND uid = ? AND tag IN(!l)',
+ $vid, $uid, [ keys %$delete ]) if keys %$delete;
- # spoiler '-1' -> NULL
- $new{$_}[1] == -1 && ($new{$_}[1] = undef) for keys %new;
+ # insert
+ my $val = join ',', map '(?,?,?,?,?,?)', keys %$insert;
+ $self->dbExec("INSERT INTO tags_vn (tag, vid, uid, vote, spoiler, ignore) VALUES $val", map
+ +($_, $vid, $uid, $insert->{$_}[0], $insert->{$_}[1]<0?undef:$insert->{$_}[1], $insert->{$_}[2]?1:0),
+ keys %$insert) if keys %$insert;
- # perform the changes
- $self->dbExec('DELETE FROM tags_vn WHERE vid = ? AND uid = ? AND tag IN(!l)',
- $vid, $uid, [ keys %delete ]) if keys %delete;
- $self->dbExec('INSERT INTO tags_vn (tag, vid, uid, vote, spoiler) VALUES (?, ?, ?, ?, ?)',
- $_, $vid, $uid, $insert{$_}[0], $insert{$_}[1]) for (keys %insert);
+ # update
$self->dbExec('UPDATE tags_vn SET vote = ?, spoiler = ?, date = NOW() WHERE tag = ? AND vid = ? AND uid = ?',
- $update{$_}[0], $update{$_}[1], $_, $vid, $uid) for (keys %update);
+ $update->{$_}[0], $update->{$_}[1]<0?undef:$update->{$_}[1], $_, $vid, $uid) for (keys %$update);
}
diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm
index 7d9b10fa..7fff2a97 100644
--- a/lib/VNDB/Handler/Tags.pm
+++ b/lib/VNDB/Handler/Tags.pm
@@ -477,19 +477,57 @@ sub vntagmod {
return $self->htmlDenied if !$self->authCan('tag');
+ my $tags = $self->dbTagStats(vid => $vid, results => 9999);
+ my $my = $self->dbTagLinks(vid => $vid, uid => $self->authInfo->{id});
+
if($self->reqMethod eq 'POST') {
return if !$self->authCheckCode;
my $frm = $self->formValidate(
- { name => 'taglinks', required => 0, default => '', maxlength => 10240, regex => [ qr/^[1-9][0-9]*,-?[1-3],-?[0-2]( [1-9][0-9]*,-?[1-3],-?[0-2])*$/, 'meh' ] }
+ { name => 'taglinks', required => 0, default => '', maxlength => 10240, regex => [ qr/^[1-9][0-9]*,-?[1-3],-?[0-2]( [1-9][0-9]*,-?[1-3],-?[0-2])*$/, 'meh' ] },
+ { name => 'overrule', required => 0, multi => 1, template => 'int' },
);
return 404 if $frm->{_err};
- $self->dbTagLinkEdit($self->authInfo->{id}, $vid, [ map [ split /,/ ], split / /, $frm->{taglinks}]);
- }
- my $my = $self->dbTagLinks(vid => $vid, uid => $self->authInfo->{id});
- my $tags = $self->dbTagStats(vid => $vid, results => 9999);
+ # convert some data in a more convenient structure for faster lookup
+ my %tags = map +($_->{id} => $_), @$tags;
+ my %old = map +($_->{tag} => $_), @$my;
+ my %new = map { my($tag, $vote, $spoiler) = split /,/; ($tag => [ $vote, $spoiler ]) } split / /, $frm->{taglinks};
+ my %over = !$self->authCan('tagmod') || !$frm->{overrule}[0] ? () : (map $new{$_} ? ($_ => 1) : (), @{$frm->{overrule}});
+
+ # hashes which need to be filled, indicating what should be changed to the DB
+ my %delete; # tag => 1
+ my %update; # tag => [ vote, spoiler ] (ignore flag is untouched)
+ my %insert; # tag => [ vote, spoiler, ignore ]
+ my %overrule; # tag => 0/1
+
+ for my $t (keys %old, keys %new) {
+ my $prev_over = $old{$t} && !$old{$t}{ignore} && $tags{$t}{overruled};
+
+ # overrule checkbox has changed? make sure to (de-)overrule the tag votes
+ $overrule{$t} = $over{$t}?1:0 if (!$prev_over && $over{$t}) || ($prev_over && !$over{$t});
+
+ # tag deleted?
+ if($old{$t} && !$new{$t}) {
+ $delete{$t} = 1;
+ next;
+ }
+
+ # and insert or update the vote
+ if(!$old{$t} && $new{$t}) {
+ # determine whether this vote is going to be ignored or not
+ my $ign = $tags{$t}{overruled} && !$prev_over && !$over{$t};
+ $insert{$t} = [ $new{$t}[0], $new{$t}[1], $ign ];
+ } elsif($old{$t}{vote} != $new{$t}[0] || (defined $old{$t}{spoiler} ? $old{$t}{spoiler} : -1) != $new{$t}[1]) {
+ $update{$t} = [ $new{$t}[0], $new{$t}[1] ];
+ }
+ }
+ $self->dbTagLinkEdit($self->authInfo->{id}, $vid, \%insert, \%update, \%delete, \%overrule);
+
+ # need to re-fetch the tags and tag links, as these have been modified
+ $tags = $self->dbTagStats(vid => $vid, results => 9999);
+ $my = $self->dbTagLinks(vid => $vid, uid => $self->authInfo->{id});
+ }
- my $frm;
my $title = mt '_tagv_title', $v->{title};
$self->htmlHeader(title => $title, noindex => 1);
@@ -505,19 +543,20 @@ sub vntagmod {
end;
end;
end;
- $self->htmlForm({ frm => $frm, action => "/v$vid/tagmod", nosubmit => 1 }, tagmod => [ mt('_tagv_frm_title'),
+ $self->htmlForm({ action => "/v$vid/tagmod", nosubmit => 1 }, tagmod => [ mt('_tagv_frm_title'),
[ hidden => short => 'taglinks', value => '' ],
[ static => nolabel => 1, content => sub {
table class => 'tgl';
thead;
Tr;
td '';
- td colspan => 2, class => 'tc_you', mt '_tagv_col_you';
+ td colspan => $self->authCan('tagmod') ? 3 : 2, class => 'tc_you', mt '_tagv_col_you';
td colspan => 3, class => 'tc_others', mt '_tagv_col_others';
end;
Tr;
td class => 'tc_tagname', mt '_tagv_col_tag';
td class => 'tc_myvote', mt '_tagv_col_rating';
+ td class => 'tc_myover', 'O' if $self->authCan('tagmod');
td class => 'tc_myspoil', mt '_tagv_col_spoiler';
td class => 'tc_allvote', mt '_tagv_col_rating';
td class => 'tc_allspoil', mt '_tagv_col_spoiler';
@@ -541,10 +580,17 @@ sub vntagmod {
Tr id => "tgl_$t->{id}";
td class => 'tc_tagname'; a href => "/g$t->{id}", $t->{name}; end;
td class => 'tc_myvote', $m->{vote}||0;
+ if($self->authCan('tagmod')) {
+ td class => 'tc_myover';
+ input type => 'checkbox', name => 'overrule', value => $t->{id},
+ $m->{vote} && !$m->{ignore} && $t->{overruled} ? (checked => 'checked') : ()
+ if $t->{cnt} > 1;
+ end;
+ }
td class => 'tc_myspoil', defined $m->{spoiler} ? $m->{spoiler} : -1;
td class => 'tc_allvote';
- tagscore !$m->{vote} ? $t->{rating} : $t->{cnt} == 1 ? 0 : ($t->{rating}*$t->{cnt} - $m->{vote}) / ($t->{cnt}-1);
- i $t->{overruled} ? (class => 'grayedout') : (), ' ('.($t->{cnt} - ($m->{vote} ? 1 : 0)).')';
+ tagscore $t->{rating};
+ i $t->{overruled} ? (class => 'grayedout') : (), " ($t->{cnt})";
b class => 'standout', style => 'font-weight: bold', ' !' if $t->{overruled};
end;
td class => 'tc_allspoil', sprintf '%.2f', $t->{spoiler};