diff options
author | Yorhel <git@yorhel.nl> | 2010-12-19 16:01:58 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2010-12-19 16:01:58 +0100 |
commit | 6cf3b2a6f7cd3fb12282e823f42a64bcdf57d012 (patch) | |
tree | 92ae905399d7ab10e5c3f8ed0106d353749c6e7b | |
parent | a129097a782ced2f2c3622f239809a937ecdb7d4 (diff) |
RFC-01: Updated and improved /u+/list
I'm sure I broke all vnlist/rlist-related features on the rest of the
site since I modified the DB abstractions. But these will all have to
be updated/rewritten anyway.
-rw-r--r-- | data/lang.txt | 81 | ||||
-rw-r--r-- | data/script.js | 20 | ||||
-rw-r--r-- | data/style.css | 18 | ||||
-rw-r--r-- | lib/VNDB/DB/ULists.pm | 116 | ||||
-rw-r--r-- | lib/VNDB/Handler/ULists.pm | 105 |
5 files changed, 202 insertions, 138 deletions
diff --git a/data/lang.txt b/data/lang.txt index a0b86b7f..515e0715 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -1137,70 +1137,70 @@ nl : Erg lang[index,_1,, (> 50 uur), (Clannad~, Umineko~, Fate/Stay Night)] # VN list statuses -:_rlst_rstat_0 +:_rlst_stat_0 en : Unknown ru : Неизвестно cs : Není známo hu : Ismeretlen nl : Onbekend -:_rlst_rstat_1 +:_rlst_stat_1 en : Pending ru : Ожидается cs : V čekání hu : Függő nl : Bezig -:_rlst_rstat_2 +:_rlst_stat_2 en : Obtained ru : Приобретено cs : Obdrženo hu : Megszerezve nl : In bezit -:_rlst_rstat_3 +:_rlst_stat_3 en : On loan ru : Взято напрокат cs : Vypůjčeno hu : Kölcsönadva nl : Uitgeleend -:_rlst_rstat_4 +:_rlst_stat_4 en : Deleted ru : Удалено cs : Smazáno hu : Törölve nl : Weggegooid -:_rlst_vstat_0 +:_vnlst_stat_0 en : Unknown ru : Неизвестно cs : Není známo hu : Ismeretlen nl : Onbekend -:_rlst_vstat_1 +:_vnlst_stat_1 en : Playing ru : В процессе cs : Ve hraní hu : Játszás nl : Mee bezig -:_rlst_vstat_2 +:_vnlst_stat_2 en : Finished ru : Завершено cs : Dohráno hu : Befejezve nl : Uitgespeeld -:_rlst_vstat_3 +:_vnlst_stat_3 en : Stalled ru : Застряло cs : Pozastaveno hu : Leragadva nl : Uitgesteld -:_rlst_vstat_4 +:_vnlst_stat_4 en : Dropped ru : Заброшено cs : Vyřazeno @@ -4903,6 +4903,13 @@ cs : Název hu : Cím nl : Titel +:_rlist_col_status +en : Status +ru*: +cs*: +hu*: +nl : + :_rlist_col_releases en : Releases ru : Выпуски @@ -4917,26 +4924,26 @@ cs : Hodnocení hu : Szavazat nl : Stem -:_rlist_selection -en : -- with selected -- -ru : -- с выбранными -- -cs : -- s vybranými -- -hu : -- kiválasztva -- -nl : -- met geselecteerde items -- +:_rlist_withvn +en : -- with selected VNs -- +ru*: +cs*: +hu*: +nl : -- met geselecteerde VNs -- -:_rlist_changerel -en : Change release status -ru : Смена статуса выпуска -cs : Změnit stav vydání -hu : Kiadás állapotának megváltoztatása -nl : Verander uitgavestatus +:_rlist_withrel +en : -- with selected releases -- +ru*: +cs*: +hu*: +nl : -- met geselecteerde uitgaven -- -:_rlist_changeplay -en : Change play status -ru : Смена статуса игры -cs : Změnit stav hraní -hu : Játszás állapot megváltoztatása -nl : Verander speelstatus +:_rlist_changestat +en : Change status +ru*: +cs*: +hu*: +nl : Verander status :_rlist_del en : remove from list @@ -4945,12 +4952,20 @@ cs : odstranit z listu hu : eltávolítás a listából nl : verwijder uit lijst +# label of the button. "Update!" in the commanding sense +:_rlist_update +en : Update +ru*: +cs*: +hu*: +nl : + :_rlist_releasenote -en : * Obtained/finished/total -ru : * Приобретено/прочитано/всего -cs : * Sehnáno/dohráno/celkem -hu : * Megszerezve/befejezve/összesen -nl : * In bezit/uitgespeeld/totaal +en : * Obtained/total +ru : * Приобретено/всего +cs : * Sehnáno/celkem +hu : * Megszerezve/összesen +nl : * In bezit/totaal diff --git a/data/script.js b/data/script.js index 4f0e808f..b30703d6 100644 --- a/data/script.js +++ b/data/script.js @@ -2216,7 +2216,7 @@ if(byId('batchedit')) { }; } -// collapse/expand row groups (/u+/list) (limited to one table on a page) +// collapse/expand row groups (/u+/list) if(byId('expandall')) { var table = byId('expandall'); while(table.nodeName.toLowerCase() != 'table') @@ -2227,11 +2227,14 @@ if(byId('expandall')) { var alltoggle = function() { allhid = !allhid; var l = byClass(table, 'tr', 'collapse'); - for(var i=0; i<l.length; i++) + for(var i=0; i<l.length; i++) { setClass(l[i], 'hidden', allhid); - setText(byName(byId('expandall'), 'i')[0], allhid ? collapsed_icon : expanded_icon); + var sel = byName(l[i], 'input')[0]; + if(sel) setClass(sel, 'hidden', allhid); + } + setText(byId('expandall'), allhid ? collapsed_icon : expanded_icon); for(var i=0; i<heads.length; i++) - setText(byName(heads[i], 'i')[0], allhid ? collapsed_icon : expanded_icon); + setText(heads[i], allhid ? collapsed_icon : expanded_icon); return false; } byId('expandall').onclick = alltoggle; @@ -2242,9 +2245,12 @@ if(byId('expandall')) { if(l.length < 1) return; var hid = !hasClass(l[0], 'hidden'); - for(var i=0; i<l.length; i++) + for(var i=0; i<l.length; i++) { setClass(l[i], 'hidden', hid); - setText(byName(this, 'i')[0], hid ? collapsed_icon : expanded_icon); + var sel = byName(l[i], 'input')[0]; + if(sel) setClass(sel, 'hidden', hid); + } + setText(this, hid ? collapsed_icon : expanded_icon); }; for(var i=0; i<heads.length; i++) heads[i].onclick = singletoggle; @@ -2290,7 +2296,7 @@ if(byId('lang_select')) { var f = function() { var l = byName('input'); for(var i=0; i<l.length; i++) - if(l[i].type == this.type && l[i].name == this.name) + if(l[i].type == this.type && l[i].name == this.name && !hasClass(l[i], 'hidden')) l[i].checked = this.checked; }; var l = byClass('input', 'checkall'); diff --git a/data/style.css b/data/style.css index 6c043caf..433873d7 100644 --- a/data/style.css +++ b/data/style.css @@ -905,15 +905,15 @@ div.votelist td.tc2 { width: 50px; text-align: right; padding-right: 10px } /***** User VN list browser ******/ #expandall, .collapse_but { cursor: pointer } -#expandall i, .collapse_but i { font-style: normal } -.browse.rlist .tc2 { width: 100px; } -.browse.rlist .tc3 { width: 70px; } -.browse.rlist .relhid .tc1 { padding-left: 40px; width: 70px; } -.browse.rlist .relhid .tc1.own { padding: 0 0 0 25px; width: 95px } -.browse.rlist .relhid input { margin-right: 5px } -.browse.rlist .relhid .tc2 { padding: 0; width: 30px; } -.browse.rlist .relhid .tc3 { width: auto } -.browse.rlist .relhid .tc4 { text-align: right } +.browse.rlist .tc1 { width: 16px; padding-bottom: 0 } +.browse.rlist .tc2 { width: 16px; padding-bottom: 0 } +.browse.rlist .tc3 { width: 60px } +.browse.rlist .tc4 { width: 60px; text-align: right; padding-top: 0; padding-bottom: 0 } +.browse.rlist .tc6 { width: 100px } +.browse.rlist .relhid .tc6 { padding-left: 15px; width: auto } +.browse.rlist .tc7 { width: 90px } +.browse.rlist .tc8 { width: 70px } +.browse.rlist tfoot select { width: 200px } /***** User notifications *****/ diff --git a/lib/VNDB/DB/ULists.pm b/lib/VNDB/DB/ULists.pm index e52cbf37..1aedfe80 100644 --- a/lib/VNDB/DB/ULists.pm +++ b/lib/VNDB/DB/ULists.pm @@ -7,56 +7,61 @@ use Exporter 'import'; our @EXPORT = qw| - dbVNListGet dbVNListList dbVNListAdd dbVNListDel + dbRListGet dbVNListGet dbVNListList dbVNListAdd dbVNListDel dbRListAdd dbRListDel dbVoteGet dbVoteStats dbVoteAdd dbVoteDel dbWishListGet dbWishListAdd dbWishListDel |; -# Simpler and more efficient version of dbVNListList below -# %options->{ uid rid } -sub dbVNListGet { +# Options: uid rid +sub dbRListGet { my($self, %o) = @_; my %where = ( 'uid = ?' => $o{uid}, - $o{rid} && !ref $o{rid} ? ( - 'rid = ?' => $o{rid} ) : (), - $o{rid} && ref $o{rid} ? ( - 'rid IN(!l)' => [$o{rid}] ) : (), + $o{rid} ? ('rid IN(!l)' => [ ref $o{rid} ? $o{rid} : [$o{rid}] ]) : (), ); return $self->dbAll(q| - SELECT uid, rid, rstat, vstat + SELECT uid, rid, rstat AS status FROM rlists !W|, \%where ); } +# Options: uid vid +sub dbVNListGet { + my($self, %o) = @_; -# %options->{ uid char voted page results sort reverse } + my %where = ( + 'uid = ?' => $o{uid}, + $o{vid} ? ('vid IN(!l)' => [ ref $o{vid} ? $o{vid} : [$o{vid}] ]) : (), + ); + + return $self->dbAll(q| + SELECT uid, vid, status + FROM vnlists + !W|, + \%where + ); +} + + +# Options: uid char voted page results sort reverse # sort: title vote -# NOTE: this function is mostly copied from 1.x, may need some rewriting... sub dbVNListList { my($self, %o) = @_; - $o{results} ||= 50; $o{page} ||= 1; - $o{voted} ||= 0; # -1: only non-voted, 0: all, 1: only voted - - # construct the global WHERE clause - my $where = $o{voted} != -1 ? 'vo.vote IS NOT NULL' : ''; - $where .= ($where?' OR ':'').q|v.id = ANY(ARRAY( - SELECT irv.vid - FROM rlists irl - JOIN releases ir ON ir.id = irl.rid - JOIN releases_vn irv ON irv.rid = ir.latest - WHERE uid = ? - ))| if $o{voted} != 1; - $where = '('.$where.') AND LOWER(SUBSTR(vr.title, 1, 1)) = \''.$o{char}.'\'' if $o{char}; - $where = '('.$where.') AND (ASCII(vr.title) < 97 OR ASCII(vr.title) > 122) AND (ASCII(vr.title) < 65 OR ASCII(vr.title) > 90)' if defined $o{char} && !$o{char}; - $where = '('.$where.') AND vo.vote IS NULL' if $o{voted} == -1; + + my %where = ( + 'vl.uid = ?' => $o{uid}, + defined($o{voted}) ? ('vo.vote !s NULL' => $o{voted} ? 'IS NOT' : 'IS') : (), + $o{char} ? ('LOWER(SUBSTR(vr.title, 1, 1)) = ?' => $o{char} ) : (), + defined $o{char} && !$o{char} ? ( + '(ASCII(vr.title) < 97 OR ASCII(vr.title) > 122) AND (ASCII(vr.title) < 65 OR ASCII(vr.title) > 90)' => 1 ) : (), + ); my $order = sprintf { title => 'vr.title %s', @@ -65,14 +70,14 @@ sub dbVNListList { # execute query my($r, $np) = $self->dbPage(\%o, qq| - SELECT vr.vid, vr.title, vr.original, COALESCE(vo.vote, 0) AS vote - FROM vn v + SELECT vr.vid, vr.title, vr.original, vl.status, COALESCE(vo.vote, 0) AS vote + FROM vnlists vl + JOIN vn v ON v.id = vl.vid JOIN vn_rev vr ON vr.id = v.latest - !s JOIN votes vo ON vo.vid = v.id AND vo.uid = ? - WHERE $where + LEFT JOIN votes vo ON vo.vid = vl.vid AND vo.uid = vl.uid + !W ORDER BY !s|, - $o{voted} == 1 ? '' : 'LEFT', $o{uid}, # JOIN if we only want votes, LEFT JOIN if we also want rlist items - $o{voted} != 1 ? $o{uid} : (), $order + \%where, $order ); # fetch releases and link to VNs @@ -83,7 +88,7 @@ sub dbVNListList { } @$r; my $rel = $self->dbAll(q| - SELECT rv.vid, rr.rid, r.latest, rr.title, rr.original, rr.released, rr.type, rl.rstat, rl.vstat + SELECT rv.vid, rr.rid, r.latest, rr.title, rr.original, rr.released, rr.type, rl.rstat AS status FROM rlists rl JOIN releases r ON rl.rid = r.id JOIN releases_rev rr ON rr.id = r.latest @@ -114,35 +119,54 @@ sub dbVNListList { } -# %options->{ uid rid rstat vstat } +# Arguments: uid vid status +# vid can be an arrayref only when the rows are already present, in which case an update is done sub dbVNListAdd { - my($self, %o) = @_; + my($self, $uid, $vid, $stat) = @_; + $self->dbExec( + 'UPDATE vnlists SET status = ? WHERE uid = ? AND vid IN(!l)', + $stat, $uid, ref($vid) ? $vid : [ $vid ] + ) + || + $self->dbExec( + 'INSERT INTO vnlists (uid, vid, status) VALUES(?, ?, ?)', + $uid, $vid, $stat + ); +} - my %s = ( - defined $o{rstat} ? ( 'rstat = ?', $o{rstat} ) : (), - defined $o{vstat} ? ( 'vstat = ?', $o{vstat} ) : (), + +# Arguments: uid, vid +sub dbVNListDel { + my($self, $uid, $vid) = @_; + $self->dbExec( + 'DELETE FROM vnlists WHERE uid = ? AND vid IN(!l)', + $uid, ref($vid) ? $vid : [ $vid ] ); - $o{rstat}||=0; - $o{vstat}||=0; +} + +# Arguments: uid rid status +# rid can be an arrayref only when the rows are already present, in which case an update is done +sub dbRListAdd { + my($self, $uid, $rid, $stat) = @_; $self->dbExec( - 'UPDATE rlists !H WHERE uid = ? AND rid IN(!l)', - \%s, $o{uid}, ref($o{rid}) eq 'ARRAY' ? $o{rid} : [ $o{rid} ] + 'UPDATE rlists SET rstat = ? WHERE uid = ? AND rid IN(!l)', + $stat, $uid, ref($rid) ? $rid : [ $rid ] ) || $self->dbExec( - 'INSERT INTO rlists (uid, rid, rstat, vstat) VALUES(!l)', - [@o{qw| uid rid rstat vstat |}] + 'INSERT INTO rlists (uid, rid, rstat) VALUES(?, ?, ?)', + $uid, $rid, $stat ); } # Arguments: uid, rid -sub dbVNListDel { +sub dbRListDel { my($self, $uid, $rid) = @_; $self->dbExec( 'DELETE FROM rlists WHERE uid = ? AND rid IN(!l)', - $uid, ref($rid) eq 'ARRAY' ? $rid : [ $rid ] + $uid, ref($rid) ? $rid : [ $rid ] ); } diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm index c8119000..cac1acec 100644 --- a/lib/VNDB/Handler/ULists.pm +++ b/lib/VNDB/Handler/ULists.pm @@ -278,26 +278,29 @@ sub vnlist { if($own && $self->reqMethod eq 'POST') { return if !$self->authCheckCode; my $frm = $self->formValidate( - { name => 'sel', required => 0, default => 0, multi => 1, template => 'int' }, - { name => 'batchedit', required => 1, enum => [ 'del', map("r$_", @{$self->{rlst_rstat}}), map("v$_", @{$self->{rlst_vstat}}) ] }, + { name => 'vid', required => 0, default => 0, multi => 1, template => 'int' }, + { name => 'rid', required => 0, default => 0, multi => 1, template => 'int' }, + { name => 'vns', required => 1, enum => [ -2, -1, @{$self->{rlst_vstat}} ] }, + { name => 'rel', required => 1, enum => [ -2, -1, @{$self->{rlst_rstat}} ] }, ); - if(!$frm->{_err} && @{$frm->{sel}} && $frm->{sel}[0]) { - $self->dbVNListDel($uid, $frm->{sel}) if $frm->{batchedit} eq 'del'; - $self->dbVNListAdd( - rid => $frm->{sel}, - uid => $uid, - $frm->{batchedit} =~ /^([rv])(\d+)$/ && $1 eq 'r' ? (rstat => $2) : (vstat => $2) - ) if $frm->{batchedit} ne 'del'; + my @vid = grep $_ > 0, @{$frm->{vid}}; + my @rid = grep $_ > 0, @{$frm->{rid}}; + if(!$frm->{_err} && @vid && $frm->{vns} > -2) { + $self->dbVNListDel($uid, \@vid) if $frm->{vns} == -1; + $self->dbVNListAdd($uid, \@vid, $frm->{vns}) if $frm->{vns} >= 0; + } + if(!$frm->{_err} && @rid && $frm->{rel} > -2) { + $self->dbRListDel($uid, \@rid) if $frm->{rel} == -1; + $self->dbRListAdd($uid, \@rid, $frm->{rel}) if $frm->{rel} >= 0; } } - my($list, $np) = $self->dbVNListList( uid => $uid, results => 50, page => $f->{p}, sort => $f->{s}, reverse => $f->{o} eq 'd', - voted => $f->{v}, + voted => $f->{v} == 0 ? undef : $f->{v} < 0 ? 0 : $f->{v}, $f->{c} ne 'all' ? (char => $f->{c}) : (), ); @@ -351,66 +354,82 @@ sub _vnlist_browse { sorturl => $url->(), pageurl => $url->('page'), header => [ - [ mt('_rlist_col_title') => 'title', 3 ], - sub { td class => 'tc2', id => 'expandall'; lit '<i>▸</i>'.mt('_rlist_col_releases').'*'; end; }, + [ '' ], + sub { td class => 'tc2', id => 'expandall'; lit '▸'; end; }, + [ mt('_rlist_col_title') => 'title' ], + [ '' ], [ '' ], + [ mt('_rlist_col_status') ], + [ mt('_rlist_col_releases').'*' ], [ mt('_rlist_col_vote') => 'vote' ], ], row => sub { my($s, $n, $i) = @_; Tr $n % 2 == 0 ? (class => 'odd') : (); - td class => 'tc1', colspan => 3; + td class => 'tc1'; input type => 'checkbox', name => 'vid', value => $i->{vid} if $own; end; + if(@{$i->{rels}}) { + td class => 'tc2 collapse_but', id => "vid$i->{vid}"; lit '▸'; end; + } else { + td class => 'tc2', ''; + } + td class => 'tc3_5', colspan => 3; a href => "/v$i->{vid}", title => $i->{original}||$i->{title}, shorten $i->{title}, 70; end; - td class => 'tc2'.(@{$i->{rels}} ? ' collapse_but' : ''), id => 'vid'.$i->{vid}; - lit '<i>▸</i>'; - my $obtained = grep $_->{rstat}==2, @{$i->{rels}}; - my $finished = grep $_->{vstat}==2, @{$i->{rels}}; - my $txt = sprintf '%d/%d/%d', $obtained, $finished, scalar @{$i->{rels}}; - $txt = qq|<b class="done">$txt</b>| if $finished > $obtained || $finished && $finished == $obtained; - $txt = qq|<b class="todo">$txt</b>| if $obtained > $finished; + td class => 'tc6', $i->{status} ? mt '_vnlst_stat_'.$i->{status} : ''; + td class => 'tc7'; + my $obtained = grep $_->{status}==2, @{$i->{rels}}; + my $total = scalar @{$i->{rels}}; + my $txt = sprintf '%d/%d', $obtained, $total; + $txt = qq|<b class="done">$txt</b>| if $total && $obtained == $total; + $txt = qq|<b class="todo">$txt</b>| if $obtained < $total; lit $txt; end; - td class => 'tc3', $i->{vote} || '-'; + td class => 'tc8', $i->{vote} || '-'; end; for (@{$i->{rels}}) { - Tr class => "collapse relhid collapse_vid$i->{vid}"; - td class => 'tc1'.($own ? ' own' : ''); - input type => 'checkbox', name => 'sel', value => $_->{rid} - if $own; - lit $self->{l10n}->datestr($_->{released}); - end; + Tr class => "collapse relhid collapse_vid$i->{vid}".($n%2 ? '':' odd'); + td class => 'tc1', ''; td class => 'tc2'; + input type => 'checkbox', name => 'rid', value => $_->{rid} if $own; + end; + td class => 'tc3', $self->{l10n}->datestr($_->{released}); + td class => 'tc4'; cssicon "lang $_", mt "_lang_$_" for @{$_->{languages}}; cssicon "rt$_->{type}", mt "_rtype_$_->{type}"; end; - td class => 'tc3'; + td class => 'tc5'; a href => "/r$_->{rid}", title => $_->{original}||$_->{title}, shorten $_->{title}, 50; end; - td colspan => 2, class => 'tc4'; - lit liststat($_); - end; + td class => 'tc6', $_->{status} ? mt '_rlst_stat_'.$_->{status} : ''; + td class => 'tc7_8', colspan => 2, ''; end; } }, $own ? (footer => sub { Tr; - td class => 'tc1', colspan => 3; - Select id => 'batchedit', name => 'batchedit'; - option mt '_rlist_selection'; - optgroup label => mt '_rlist_changerel'; - option value => "r$_", mt "_rlst_rstat_$_" - for (@{$self->{rlst_rstat}}); - end; - optgroup label => mt '_rlist_changeplay'; - option value => "v$_", mt "_rlst_vstat_$_" + td class => 'tc1'; input type => 'checkbox', name => 'vid', value => -1, class => 'checkall'; end; + td class => 'tc2'; input type => 'checkbox', name => 'rid', value => -1, class => 'checkall'; end; + td class => 'tc3_6', colspan => 4; + Select id => 'vns', name => 'vns'; + option value => -2, mt '_rlist_withvn'; + optgroup label => mt '_rlist_changestat'; + option value => $_, mt "_vnlst_stat_$_" for (@{$self->{rlst_vstat}}); end; - option value => 'del', mt '_rlist_del'; + option value => -1, mt '_rlist_del'; + end; + Select id => 'rel', name => 'rel'; + option value => -2, mt '_rlist_withrel'; + optgroup label => mt '_rlist_changestat'; + option value => $_, mt "_rlst_stat_$_" + for (@{$self->{rlst_rstat}}); + end; + option value => -1, mt '_rlist_del'; end; + input type => 'submit', value => mt '_rlist_update'; end; - td class => 'tc2', colspan => 2, mt '_rlist_releasenote'; + td class => 'tc7_8', colspan => 2, mt '_rlist_releasenote'; end; }) : (), ); |