diff options
author | yorhel <yorhel@1fe2e327-d9db-4752-bcf7-ef0cb4a1748b> | 2008-04-13 13:45:20 +0000 |
---|---|---|
committer | yorhel <yorhel@1fe2e327-d9db-4752-bcf7-ef0cb4a1748b> | 2008-04-13 13:45:20 +0000 |
commit | d7046f5d38004ff20739798c18f5796c31676546 (patch) | |
tree | 1639e6a8c3b74588bff7be6aaf6cf5e04e3bc63f /data |
W00t, VNDB on SVN!
git-svn-id: svn://vndb.org/vndb@1 1fe2e327-d9db-4752-bcf7-ef0cb4a1748b
Diffstat (limited to 'data')
-rw-r--r-- | data/tpl/defs.pl | 482 | ||||
-rw-r--r-- | data/tpl/docs | 298 | ||||
-rw-r--r-- | data/tpl/error | 45 | ||||
-rw-r--r-- | data/tpl/faq | 75 | ||||
-rw-r--r-- | data/tpl/hist | 103 | ||||
-rw-r--r-- | data/tpl/home | 67 | ||||
-rw-r--r-- | data/tpl/main | 14 | ||||
-rw-r--r-- | data/tpl/myvotes | 30 | ||||
-rw-r--r-- | data/tpl/page | 140 | ||||
-rw-r--r-- | data/tpl/pbrowse | 45 | ||||
-rw-r--r-- | data/tpl/pedit | 45 | ||||
-rw-r--r-- | data/tpl/ppage | 58 | ||||
-rw-r--r-- | data/tpl/redit | 70 | ||||
-rw-r--r-- | data/tpl/rpage | 61 | ||||
-rw-r--r-- | data/tpl/useredit | 34 | ||||
-rw-r--r-- | data/tpl/userlist | 54 | ||||
-rw-r--r-- | data/tpl/userlogin | 14 | ||||
-rw-r--r-- | data/tpl/userpage | 13 | ||||
-rw-r--r-- | data/tpl/userpass | 21 | ||||
-rw-r--r-- | data/tpl/userreg | 38 | ||||
-rw-r--r-- | data/tpl/vnbrowse | 87 | ||||
-rw-r--r-- | data/tpl/vnedit | 94 | ||||
-rw-r--r-- | data/tpl/vnlist | 74 | ||||
-rw-r--r-- | data/tpl/vnpage | 171 | ||||
-rw-r--r-- | data/tpl/vnpage_rel | 51 | ||||
-rw-r--r-- | data/tpl/vnpage_rg | 11 | ||||
-rw-r--r-- | data/tpl/vnpage_stats | 68 |
27 files changed, 2263 insertions, 0 deletions
diff --git a/data/tpl/defs.pl b/data/tpl/defs.pl new file mode 100644 index 00000000..b68faab0 --- /dev/null +++ b/data/tpl/defs.pl @@ -0,0 +1,482 @@ +[[! + +use Time::CTime (); +use Algorithm::Diff 'sdiff'; +use POSIX ('ceil', 'floor'); + +my %p; # $X->{page} global page data +my %d; # $X->{page}->{$p} local page data + +# redefine _hchar - usually a bad idea, but who cares +sub _hchar {local$_=shift||return'';s/&/&/g;s/</</g;s/>/>/g;s/"/"/g;s/\r?\n/ <br \/>\n/g;return$_;} + +sub formatdate {return _hchar(Time::CTime::strftime($_[0],gmtime($_[1]||0)))||'';} +sub txt {local$_=shift||return'';s/&/&/g;s/</</g;s/>/>/g;return$_;} +sub art2str {my$r='';$r.=($r?' & ':'').$_->{name}foreach (@{$_[0]->{artists}});return $_[1]?$r:_hchar($r);} +sub calctime {my$r=shift;return'0:00:00'if!$r;my$x=sprintf'%d:%02d:%02d',int($r/3600),int(($r%3600)/60),($r%3600)%60;return $x;} +sub shorten {local$_=shift||return'';return length>$_[0]?substr($_,0,$_[0]-3).'...':$_}; + +# Date string format: yyyy-mm-dd +# y = 0 -> Unknown +# y = 9999 -> TBA (To Be Announced) +# m = 0 -> Month + day unknown, year known +# d = 0 -> Day unknown, month + year known +sub datestr { + my $d = $_[0]||'00000000'; + my @d = map { int } $1, $2, $3 if $d =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/; + return 'unknown' if $d[0] == 0; + my $r = sprintf !$d[1] ? '%04d' : !$d[2] ? '%04d-%02d' : '%04d-%02d-%02d', @d; + my $b = $r gt Time::CTime::strftime("%Y-%m-%d", gmtime()); + $r = 'TBA' if $d[0] == 9999; + return ($b?'<b class="future">':'').$r.($b?'</b>':''); +} +sub mediastr { + return join(', ', map { + $_->{medium} =~ /^(cd|dvd|gdr|blr)$/ + ? sprintf('%d %s%s', $_->{qty}, $VNDB::MED->{$_->{medium}}, $_->{qty}>1?'s':'') + : $VNDB::MED->{$_->{medium}} + } @{$_[0]}); +} +sub sortbut { # url, col + my $r=' '; my $u = _hchar($_[0]); + $u .= $u =~ /\?/ ? ';' : '?'; + for ('a', 'd') { + my $chr = $_ eq 'd' ? "\x{25BE}" : "\x{25B4}"; + $r .= $d{order}[0] eq $_[1] && $d{order}[1] eq $_ ? $chr : + sprintf '<a href="%ss=%s;o=%s">%s</a>', $u, $_[1], $_, $chr; + } + return $r; +} +sub pagebut { # url + my @br; my $ng = $_[0] =~ /\?/ ? ';' : '?'; + push @br, sprintf '<a href="%s"><- previous</a>', $_[0].($d{page}-2 ? $ng.'p='.($d{page}-1) : '') if $d{page} > 1; + push @br, sprintf '<a href="%s">next -></a>', $_[0].$ng.'p='.($d{page}+1) if $d{npage}; + return $#br >= 0 ? ('<p class="browse">( '.join(' | ', @br).' )</p>') : ''; +} +sub wraplong { # text, margin + local $_ = $_[0]; + my $m = $_[1]/2; + s/([^\s\r\n]{$m})([^\s\r\n])/$1 $2/g; + return $_; +} + + +sub wordsplit { # split a string into an array of words, but make sure to not split HTML tags +# return [ split //, $_[0] ]; + my @a; + my $in=''; + for (split /\s+/, $_[0]) { + my $gt = () = />/g; + my $lt = () = /</g; + if($in && $gt > $lt) { + push @a, $in.$_; + $in=''; + } elsif($lt > $gt || $in) { + $in .= $_.' '; + } else { + push @a, $_; + }; + } + push @a, $in if $in; + return \@a; +} + +sub cdiff { # obj1, obj2, @items->[ short, name, serialise, diff, [parsed_x, parsed_y] ] + my($x, $y, @items, @c) = @_; + # serialise = 0 -> integer, 1 -> string, CODEref -> code + + my $type = defined $$y{minage} ? 'r' : defined $$y{length} ? 'v' : 'p'; + my $pre = '<div id="revbrowse">'. + ($$y{next} ? qq|<a href="/$type$$y{id}?rev=$$y{next}" id="revnext">later revision -></a>| : ''). + ($x ? qq|<a href="/$type$$y{id}?rev=$$x{cid}" id="revprev"><- earlier revision</a>| : ''). + qq|<a href="/$type$$y{id}" id="revmain">$type$$y{id}</a> </div>|; + + if(!$x) { # just show info about the revision if there is no previous edit + return $pre.qq|<div id="tmc"><b>Revision $$y{cid}</b> (<a href="/$type$$y{id}/edit?rev=$$y{cid}">edit</a>)<br />By <a href="/u$$y{requester}">$$y{username}</a> on |. + formatdate('%Y-%m-%d at %R', $$y{added}).'<br /><b>Edit summary:</b><br /><br />'. + summary($$y{comments}, 0, '[no summary]').'</div>'; + } + for (@items) { + $_->[4] = !$_->[2] ? $x->{$_->[0]}||'0' : !ref($_->[2]) ? _hchar(wraplong($x->{$_->[0]}||'[empty]',60)) : &{$_->[2]}($x->{$_->[0]})||'[empty]'; + $_->[5] = !$_->[2] ? $y->{$_->[0]}||'0' : !ref($_->[2]) ? _hchar(wraplong($y->{$_->[0]}||'[empty]',60)) : &{$_->[2]}($y->{$_->[0]})||'[empty]'; + push(@c, $_) if $_->[4] ne $_->[5]; + if($_->[3] && $_->[4] ne $_->[5]) { + my($rx,$ry,$ch) = ('','','u'); + for (sdiff(wordsplit($_->[4]), wordsplit($_->[5]))) { + if($ch ne $_->[0]) { + if($ch ne 'u') { + $rx .= '</b>'; + $ry .= '</b>'; + } + $rx .= '<b class="diff_del">' if $_->[0] eq '-' || $_->[0] eq 'c'; + $ry .= '<b class="diff_add">' if $_->[0] eq '+' || $_->[0] eq 'c'; + } + $ch = $_->[0]; + $rx .= $_->[1].' ' if $ch ne '+'; + $ry .= $_->[2].' ' if $ch ne '-'; + } + $_->[4] = $rx; + $_->[5] = $ry; + } + } + return $pre.'<table id="tmc"><thead><tr><td class="tc1"> </td>'. + qq|<td class="tc2"><b>Revision $$x{cid}</b> (<a href="/$type$$y{id}/edit?rev=$$x{cid}">edit</a>)<br />By <a href="/u$$x{requester}">$$x{username}</a> on |.formatdate('%Y-%m-%d at %R', $$x{added}).'</td>'. + qq|<td class="tc3"><b>Revision $$y{cid}</b> (<a href="/$type$$y{id}/edit?rev=$$y{cid}">edit</a>)<br />By <a href="/u$$y{requester}">$$y{username}</a> on |.formatdate('%Y-%m-%d at %R', $$y{added}).'</td>'. + '</tr><tr></tr><tr><td> </td><td colspan="2"><b>Edit summary of revision '.$$y{cid}.'</b><br /><br />'.summary($$y{comments}, 0, '[no summary]').'<br /><br /></td></tr></thead>'. + join('',map{ + '<tr><td class="tc1">'.$_->[1].'</td><td class="tc2">'.$_->[4].'</td><td class="tc3">'.$_->[5].'</td></tr>' + } @c).'</table>'; +} + + +sub summary { # cmd, len, def + return $_[2]||'' if !$_[0]; + my $res = ''; + my $len = 0; + my $as = 0; + for (split / /, $_[0]) { + next if !$_; + my $l = length; + s/\&/&/g; + s/>/>/g; + s/</</g; + while(s/\[url=((https?:\/\/|\/)[^\]>]+)\]/<a href="$1" rel="nofollow">/) { + $l -= length($1)+6; + $as++; + } + if(!$as && s/(http|https):\/\/(.+[0-9a-zA-Z\/])/<a href="$1:\/\/$2" rel="nofollow">link<\/a>/) { + $l = 4; + } elsif(!$as) { + s/^([uvpr][0-9]+)[^\w]*$/<a href="\/$1">$1<\/a>/; + } + while(s/\[\/url\]/<\/a>/) { + $l -= 6; + $as--; + } + $len += $l + 1; + last if $_[1] && $len > $_[1]; + $res .= "$_ "; + } + $res =~ y/\r\n/ / if $_[1]; + $res =~ s/\r?\n/<br \/>/g if !$_[1]; + $res =~ s/ +$//; + $res .= '</a>' x $as if $as; + $res .= '...' if $_[1] && $len > $_[1]; + return $res; +} + + +sub ttabs { # [vrp], obj, sel + my($t, $o, $s) = @_; + $s||=''; + my @act = ( + !$s?'%s':'<a href="/%s">%1$s</a>', + $$o{locked} ? + '<b>locked for editing</b>' : (), + $p{Authlock} ? + sprintf('<a href="/%%s/lock">%s</a>', $$o{locked} ? 'unlock' : 'lock') : (), + $p{Authdel} ? ( + '<a href="/%s/del" id="idel">del</a>', + sprintf('<a href="/%%s/hide"%s>%s</a>', $t eq 'v' ? ' id="vhide"' : '', $$o{hidden} ? 'unhide' : 'hide') + ) : (), + !$$o{locked} || ($p{Authedit} && $p{Authlock}) ? + ($s eq 'edit' ? 'edit' : '<a href="/%s/edit" '.($t eq 'v' || $t eq 'r' ? 'class="dropdown" rel="editDD"':'').'>edit</a>') : (), + + $p{Authhist} ? + ($s eq 'hist' ? 'history' : '<a href="/%s/hist">history</a>') : (), + ); + return '<p class="mod">< '.join(' - ', map { sprintf $_, $t.$$o{id} } @act).' ></p>'.( + $t eq 'v' ? qq| +<div id="editDD" class="dropdown"> + <ul> + <li><a href="/v$$o{id}/edit" rel="nofollow">Edit all</a></li> + <li><a href="/v$$o{id}/edit?fh=info" rel="nofollow">General info</a></li> + <li><a href="/v$$o{id}/edit?fh=cat" rel="nofollow">Categories</a></li> + <li><a href="/v$$o{id}/edit?fh=rel" rel="nofollow">Relations</a></li> + <li><a href="/v$$o{id}/edit?fh=img" rel="nofollow">Upload image</a></li> + <li><a href="/v$$o{id}/add" rel="nofollow">Add release</a></li> + </ul> +</div>| : $t eq 'r' ? qq| +<div id="editDD" class="dropdown"> + <ul> + <li><a href="/r$$o{id}/edit" rel="nofollow">Edit all</a></li> + <li><a href="/r$$o{id}/edit?fh=info" rel="nofollow">General info</a></li> + <li><a href="/r$$o{id}/edit?fh=pnm" rel="nofollow">Platforms & media</a></li> + <li><a href="/r$$o{id}/edit?fh=prod" rel="nofollow">Producers</a></li> + <li><a href="/r$$o{id}/edit?fh=rel" rel="nofollow">Relations</a></li> + </ul> +</div>| : '' + ); +} + + + +my %pagetitles = ( + faq => 'Frequently Asked Questions', + userlogin => 'Login', + userreg => 'Register a new account', + userpass => 'Forgot your password?', + home => 'Visual Novel Database', + pbrowse => 'Browse producers', + userlist => 'Browse users', + myvotes => sub { + return $p{myvotes}{user}{username} eq $p{AuthUsername} ? 'My votes' : ('Votes by '.$p{myvotes}{user}{username}); }, + userpage => sub { + return 'User: '.$p{userpage}{user}{username} }, + vnlist => sub { + return $p{vnlist}{user}{username} eq $p{AuthUsername} ? 'My visual novel list' : ($p{vnlist}{user}{username}.'\'s visual novel list'); }, + useredit => sub { + return !$p{useredit}{adm} ? 'My account' : 'Edit '.$p{useredit}{form}{username}.'\'s account'; }, + ppage => sub { + return $p{ppage}{prod}{name} }, + pedit => sub { + return $p{pedit}{id} ? sprintf('Edit %s', $p{pedit}{form}{name}) : 'Add a new producer'; }, + vnedit => sub { + return $p{vnedit}{id} ? sprintf('Edit %s', $p{vnedit}{form}{title}) : 'Add a new visual novel'; }, + redit => sub { + return $p{redit}{id} ? sprintf('Edit %s', $p{redit}{rel}{title}) : sprintf('Add release to %s', $p{redit}{vn}{title}); }, + vnpage => sub { return $p{vnpage}{vn}{title}; }, + vnrg => sub { return 'Relations for '.$p{vnrg}{vn}{title} }, + vnstats => sub { return 'User statistics for '.$p{vnstats}{vn}{title} }, + vnbrowse => sub { + return $p{vnbrowse}{chr} eq 'search' ? sprintf 'Search results for "%s"', $p{searchquery} : + $p{vnbrowse}{chr} eq 'cat' ? 'Browse categories' : + $p{vnbrowse}{chr} eq 'mod' ? 'Visual Novels awaiting moderation' : + $p{vnbrowse}{chr} eq 'all' ? 'Browse all visual novels' : + $p{vnbrowse}{chr} eq '0' ? 'Browse by char: Other' : + sprintf 'Browse by char: %s', uc $p{vnbrowse}{chr}; }, + rpage => sub { + return $p{rpage}{rel}{romaji} || $p{rpage}{rel}{title} }, + hist => sub { + return !$p{hist}{id} || !$p{hist}{type} ? 'Recent changes' : + $p{hist}{type} eq 'u' ? 'Recent changes by '.$p{hist}{title} : 'Edit history of '.$p{hist}{title}; }, + docs => sub { + return ( + 'Categories', 'Adding/editing a visual novel', 'Adding/editing a release', + 'Adding/editing a producer', 'General guidelines', 'Error parsing form', + )[$p{docs}{p}-1]||'' } +); +sub gettitle{$p{$_}&&($p{PageTitle}=ref($pagetitles{$_}) eq 'CODE' ? &{$pagetitles{$_}} : $pagetitles{$_}) for (keys%pagetitles);} + + +# +# F O R M E R R O R H A N D L I N G +# +my %formerr_names = ( + mail => 'Email', + username => 'Username', + userpass => 'Password', + pass1 => 'Password', + pass2 => 'Password (second)', + title => 'Title', + desc => 'Description', + rel => 'Relation', + romaji => 'Romanized title', + lang => 'Language', + web => 'Website', + released => 'Release date', + platforms => 'Platforms', + media => 'Media', + name => 'Name', + vn => 'Visual novel relations', +); +my @formerr_msgs = ( + sub { return sprintf 'Field "%s" is required.', @_ }, + sub { return sprintf '%s should have at least %d characters.', @_ }, + sub { return sprintf '%s is too large! Only %d characters allowed.', @_ }, + sub { return + $_[1] eq 'mail' ? 'Invalid email address' : + $_[1] eq 'url' ? 'Invalid URL' : + $_[1] eq 'pname' ? sprintf('%s can only contain alfanumeric characters!', $_[0]) : + $_[1] eq 'asciiprint' ? sprintf('Only ASCII characters are allowed at %s', $_[0]) : + $_[1] eq 'int' ? sprintf('%s should be a number!', $_[0]) : ''; + }, + sub { return sprintf '%s: invalid item selected', @_ }, + sub { return 'Invalid unicode, are you sure your browser works fine?' }, +); +my %formerr_exeptions = ( + loginerr => 'Invalid username or password', + badpass => 'Passwords do not match', + usrexists => 'Username already exists, please choose an other one', + mailexists => 'There already is a user with that email address, please request a new password if you forgot it', + nomail => 'No user found with that email address', + nojpeg => 'Image is not in JPEG format!', + toolarge => 'Image is too large (in filesize), try to compress it a little', + imgsize => 'Image is too large (in height/width), try to resize it a little', +); +sub formerr { + my @err = ref $_[0] eq 'ARRAY' ? @{$_[0]} : (); + return '' if $#err < 0; + my @msgs; + my $ret = '<span class="warning"> + Error:<ul>'; + $ret .= sprintf " <li>%s</li>\n", + /^([a-z0-9]+)_([0-9]+)_?(.*)$/ ? &{$formerr_msgs[$2-1]}($formerr_names{$1}, $3?$3:'') : $formerr_exeptions{$_} + foreach (@err); + $ret .= "</ul>\n</span>\n"; +} + +# +# F O R M C R E A T I N G +# + +# args = [ +# { +# type => $type, +# %options +# }, ... +# ], $formobj +# +# $type $formobj %options ( required, [ optional ] ) +# error X ( ) +# startform ( action, [ upload ] ) +# endform ( ) +# input X ( short, name, [ class, default ] ) +# pass ( short, name ) +# upload ( short, name, [ class ] ) +# hidden X ( short, [ value ] ) +# textarea X ( short, name, [ rows, cols, class ] ) +# select X ( short, name, options, [ class ] ) # options = arrayref of hashes with keys: short, name +# as X ( name ) +# trans X ( ) +# submit ( [ text, short ] ) +# sub ( title ) +# check X ( short, name, [ value ] ) +# static ( text, raw [ name, class ] ) +# date X ( short, name ) +# +sub cform { + my $obj = shift; + my $frm = shift; + my $ret = ''; + my $csub = ''; + for (@$obj) { + $_->{class} ||= ''; + $_->{class} .= ' sf_'.$csub if $csub && $_->{class} !~ /nohid/; + $_->{class} .= ' formhid' if $csub && $frm->{_hid} && !$frm->{_hid}{$csub} && $_->{class} !~ /nohid/; + $_->{name} = '<i>*</i> '.$_->{name} if $_->{r}; + + # error + if($_->{type} eq 'error') { + $ret .= formerr($frm->{_err}); + # startform + } elsif($_->{type} eq 'startform') { + $ret .= sprintf qq|<form action="/nospam?%s" method="post" accept-charset="utf-8"%s>\n|, + $_->{action}, $_->{upload} ? ' enctype="multipart/form-data"' : ''; + $ret .= sprintf qq| <input type="hidden" class="hidden" name="fh" id="_hid" value="%s" />\n|, + $frm->{_hid} ? _hchar(join(',', keys %{$frm->{_hid}})) : '' if $_->{fh}; + $ret .= qq|<p class="formnotice">Items denoted by a red asterisk (<i>*</i>) are required.</p>\n| + if scalar grep { $_->{r} } @$obj; + $ret .= "<ul>\n"; + # endform + } elsif($_->{type} eq 'endform') { + $ret .= qq|</ul></form>\n|; + # input + } elsif($_->{type} eq 'input') { + $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n %s<input type="text" class="text" name="%2\$s" id="%2\$s" value="%s" />\n</li>\n|, + $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}, $_->{pre} ? '<i>'.$_->{pre}.'</i>' : '', + _hchar($frm->{$_->{short}}?$frm->{$_->{short}}:$_->{default}); + # pass + } elsif($_->{type} eq 'pass') { + $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <input type="password" class="text" name="%2\$s" id="%2\$s" />\n</li>\n|, + $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}; + # upload + } elsif($_->{type} eq 'upload') { + $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <input type="file" class="text" name="%2\$s" id="%2\$s" />\n</li>\n|, + $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}; + # hidden + } elsif($_->{type} eq 'hidden') { + $ret .= sprintf qq| <input type="hidden" class="hidden" name="%s" id="%1\$s" value="%s" />\n|, + $_->{short}, _hchar($_->{value} || $frm->{$_->{short}}); + # textarea + } elsif($_->{type} eq 'textarea') { + $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <textarea name="%2\$s" id="%2\$s" rows="%s" cols="%s">%s</textarea>\n</li>\n|, + $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}, $_->{rows}||15, $_->{cols}||70, txt($frm->{$_->{short}}); + # select + } elsif($_->{type} eq 'select') { + $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <select name="%2\$s" id="%2\$s">\n%s</select>\n</li>\n|, + $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}, eval { + my $r=''; + for my $s (@{$_->{options}}) { + $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, + $s->{short}, defined $frm->{$_->{short}} && $frm->{$_->{short}} eq $s->{short} ? ' selected="selected"' : '', $s->{name}; + } + return $r; + }; + # jssel + } elsif($_->{type} eq 'jssel') { + (my $oname = $_->{name}) =~ s/^<i>\*<\/i>//; + $ret .= sprintf + qq|<li%s>\n| + .qq| <label for="%s_select">%s</label>\n| + .qq| <select name="%s_select" id="%s_select" multiple="multiple" size="5" class="multiple">\n| + .qq| <option value="0_new" style="font-style: italic">Add %s...</option>\n| + .qq| </select>\n| + .qq| <div id="%s_conts">\n| + .qq| Loading...\n| + .qq| </div>\n| + .qq| <input type="hidden" name="%s" id="%s" class="hidden" value="%s" />\n| + .qq|</li>\n|, + $_->{class} ? ' class="'.$_->{class}.'"' : '', + $_->{sh}, $_->{name}, $_->{sh}, $_->{sh}, $oname, $_->{sh}, $_->{short}, $_->{short}, _hchar($frm->{$_->{short}}); + # submit + } elsif($_->{type} eq 'submit') { + $ret .= sprintf qq|<li class="nolabel">\n <br /><input type="submit" class="submit" value="%s"%s />\n </li>\n|, + $_->{text} || 'Verstuur', $_->{short} ? sprintf(' name="%s" id="%1$s"', $_->{short}) : ''; + # sub + } elsif($_->{type} eq 'sub') { + $ret .= sprintf qq|<li class="subform">\n <a href="#" class="s_%s">%s %s</a>\n</li>\n|, + $_->{short}, $frm->{_hid} && !$frm->{_hid}{$_->{short}} ? '▸' : '▾', $_->{title}; + $csub = $_->{short}; + # check + } elsif($_->{type} eq 'check') { + $ret .= sprintf qq|<li class="nolabel%s">\n <input type="checkbox" name="%s" id="%2\$s" value="%s"%s />\n <label for="%2\$s" class="checkbox">%s</label>\n</li>\n|, + $_->{class} ? ' '.$_->{class} : '', + $_->{short}, $_->{value} || 'true', $frm->{$_->{short}} ? ' checked="checked"' : '', $_->{name}; + # static + } elsif($_->{type} eq 'static') { + $ret .= $_->{name} + ? sprintf qq|<li%s>\n <label>%s</label>\n <p>%s</p>\n</li>|, $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{name}, $_->{text} + : $_->{raw} + ? sprintf qq|<li%s>\n %s\n</li>|, $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{text} + : sprintf qq|<li class="nolabel%s">\n %s\n</li>|, $_->{class} ? ' '.$_->{class} : '', $_->{text}; + # date + } elsif($_->{type} eq 'date') { + $ret .= sprintf qq|<li class="date%s">\n <label for="%s">%s</label>\n|, + $_->{class} ? ' '.$_->{class} : '', $_->{short}, $_->{name}; + $ret .= sprintf qq| <select name="%s" id="%s">\n%s</select>\n|, + $_->{short}, $_->{short}, eval { + my $r=''; + for my $s (0, 1990..((localtime())[5]+1905), 9999) { + $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, + $s, $frm->{$_->{short}} && ($frm->{$_->{short}}[0]||0) == $s ? ' selected="selected"' : '', + !$s ? '-year-' : $s < 9999 ? $s : 'TBA'; + } + return $r; + }; + $ret .= sprintf qq| <select name="%s" id="%s_m">\n%s</select>\n|, + $_->{short}, $_->{short}, eval { + my $r=''; + for my $s (0..12) { + $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, + $s, $frm->{$_->{short}} && ($frm->{$_->{short}}[1]||0) == $s ? ' selected="selected"' : '', + $s ? $Time::CTime::MonthOfYear[$s-1] : '-month-'; + } + return $r; + }; + $ret .= sprintf qq| <select name="%s" id="%s_d">\n%s</select>\n</li>\n|, + $_->{short}, $_->{short}, eval { + my $r=''; + for my $s (0..31) { + $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, + $s, $frm->{$_->{short}} && ($frm->{$_->{short}}[2]||0) == $s ? ' selected="selected"' : '', + $s ? $s : '-day-'; + } + return $r; + }; + } + } + return $ret; +} + +]] diff --git a/data/tpl/docs b/data/tpl/docs new file mode 100644 index 00000000..1ca812c2 --- /dev/null +++ b/data/tpl/docs @@ -0,0 +1,298 @@ +[[ if(0) { ]] +<p class="mod">< <a href="/d1">categories</a> - <a href="/d2">visual novels</a> - <a href="/d3">releases</a> - <a href="/d4">producers</a> - <a href="/d5">general guidelines</a> ></p> +[[ } ]] +<h2>[[: $p{PageTitle} ]]</h2> +<div id="dpage"> + +[[ # C A T E G O R I E S + if($d{p} == 1) { ]] + +<h3>Elements</h3> +<p> + ...own interpretation for now... (Should be documented at some time, too) +</p> + + +<h3>Gameplay</h3> +<p> + This category is used to describe the gameplay or game engine. +</p> +<dl> + <dt>Visual Novel</dt><dd> + All games where the text is overlaid on the background and there is no special + dialog-box fall under this category. Can be abbreviated as VN or NVL. + </dd><dt>Adventure</dt><dd> + This is the opposite of the <i>Visual Novel</i> category: The text is presented + in a special window, usually at the bottom of the screen. In some (rare) cases + a game will switch between both styles, for these games both the <i>Visual Novel</i> + and <i>Adventure</i> categories should be selected. Can be abbreviated as ADV or AVG. + </dd><dt>Action</dt><dd> + This category indicates that the game includes a gameplay that challenges the + player's speed, dexterity and reaction time. Common examples are fighting games, + puzzles that should be solved within a short time limit, and shooter games. + </dd><dt>RPG</dt><dd> + Abbreviation for Role Playing Game. An RPG is a game in which you assume the + role of a character introduced to a vast world to be explored. Games typically + place emphasis on gaining equipment and experience points through fighting enemies + in order to advance through different levels. + </dd><dt>Strategy</dt><dd> + A strategy game is one that challenges the player to think critically in order + to achieve victory. + </dd><dt>Simulation</dt><dd> + A simulation game attempts to recreate aspects of reality and puts the player in + control. + </dd> +</dl> + +<h3>Plot</h3> +<p> + Indicates the plot type of a game. There are only two options: <i>Branching</i> and + <i>Linear</i>. +</p> +<dl> + <dt>Linear</d><dd> + A game with a linear plot has a static story; it is not possible to get different paths + or endings. Many games in this category do not prompt the player with choices and simply + tell the story as it is. This is, however, not a rule: it is also possible for a game + to provide choises, but they have no influence on the story itself. (e.g. + <a href="/v3">Utawarerumono</a>) + </dd><dt>Branching</dt><dd> + A game with a branching plot has a story whose path is directly affected by choices + made by the player during the game. These different paths are sometimes referred to + as "arcs" when they pertain to the stories of different female characters within a game. + </dd> +</dl> + +<h3>Time</h3> +<p> + Indicates the time period in which the story has been set. +</p> +<dl> + <dt>Future</dt><dd> + The game is set in a time beyond that of our own. Games may incorperate elements of + future technologies or events yet-to-come. + </dd><dt>Present</dt><dd> + The game is set in the current day. + </dd><dt>Past</dt><dd> + The game is set in a time before our own. Games may or may not adhere to historic fact. + </dd> +</dl> + +<h3>Place</h3> +<p> + Indicates the place in which the story is told. +</p> +<dl> + <dt>Earth</dt><dd> + The game takes place on our own planet. + </dd><dt>Fantasy World</dt><dd> + The game takes place on another world. The game's environment could be similar + to that of our own with a few significant changes, but it could also be + radically different. + </dd><dt>Space</dt><dd> + The game takes place in the vacuum of space between celestial bodies. For example, + this category can be used to define games where the characters may inhabit + spaceships that journey across the universe. + </dd> +</dl> + +<h3>Sexual content</h3> +<p> + Indicates the types of sexual content that the game contains. +</p> +<dl> + <dt>Sexual content</dt><dd> + This is a generic category to indicate the presence of any sexual content in the + game. If there is any such content, this category should be selected. + </dd><dt>Bestiality</dt><dd> + Sexual activity between characters and animals.<br /> + <i>No catgirls, I guess?</i> + </dd><dt>Incest</dt><dd> + Sexual activity between members of the same family. Most of the time under the + justification of participants not blood related (step-sister etc.). + </dd><dt>Lolicon</dt><dd> + The usage of female characters with childlike features in sexual situations. + </dd><dt>Shotacon</dt><dd> + The usage of male characters with childlike features in sexual situations. + </dd><dt>Yaoi</dt><dd> + Sexual content depicting activity between males. + </dd><dt>Yuri</dt><dd> + Sexual content depicting activity between females. + </dd><dt>Rape</dt><dd> + Situation in which a character is made to engage in sexual activities against + their will. + </dd> +</dl> + + + + +[[ } # V I S U A L N O V E L A D D / E D I T + if($d{p} == 2) { ]] + +<p> + Blahblah about what we define as VN? Or should that be in <a href="/d5">General guidelines</a>? +</p> + +<h3>General info</h3> +<dl> + <dt>*Title</dt><dd> + .. + </dd><dt>Aliases</dt><dd> + .. + </dd><dt>*Description</dt><dd> + .. + </dd><dt>Length</dt><dd> + .. + </dd><dt>External links</dt><dd> + .. + </dd> +</dl> + +<h3>Categories</h3> +<p> + See <a href="/d1">Categories</a>. +</p> + +<h3>Image</h3> +<p> + <i>General image guidelines and when to use the NSFW warning</i> +</p> + +<h3>Relations</h3> +<p> + <i>When to add relation, and document direct and reverse relations</i><br /> + <i>(Stolen from AniDB, needs some rewriting)</i> +</p> +<dl> + <dt>Sequel</dt><dd> + Continuation of the story. <=><i>Prequel</i>. + </dd><dt>Prequel</dt><dd> + The story happens before the original story.<=><i>Sequel</i>. + </dd><dt>Same setting</dt><dd> + Same universe/world/reality/timeline, completely different characters. + </dd><dt>Alternative setting</dt><dd> + Same characters, different universe/world/reality/timeline. + </dd><dt>Alternative version</dt><dd> + Same setting, same characters, story is told differently. + </dd><dt>Same characters</dt><dd> + Shares one or more characters, story is unrelated. + </dd><dt>Side story</dt><dd> + Takes place sometime during the parent storyline. <=><i>Parent story</i> + </dd><dt>Parent story</dt><dd> + .. <=><i>Side story</i>. + </dd><dt>Summary</dt><dd> + Summarizes full story, may contain additional stuff. <=><i>Full story</i>. + </dd><dt>Full story</dt><dd> + Full version of the summarized story. <=><i>Summary</i>. + </dd><dt>Other</dt><dd> + .. + </dd> +</dl> + + + + + + +[[ } # R E L E A S E A D D / E D I T + if($d{p} == 3) { ]] + +<p> + <i>When to add a release</i> +</p> + +<h3>General info</h3> +<dl> + <dt>*Type</dt><dd> + .. + </dd><dt>*Title (romaji)</dt><dd> + .. + </dd><dt>Original title</dt><dd> + .. + </dd><dt>*Language</dt><dd> + .. + </dd><dt>Official website</dt><dd> + .. + </dd><dt>Release date</dt><dd> + .. + </dd><dt>Age rating</dt><dd> + .. + </dd><dt>Notes</dt><dd> + .. + </dd> +</dl> + +<h3>Platforms & Media</h3> +<dl> + <dt>Platforms</dt><dd> + .. + </dd><dt>Media</dt><dd> + .. + </dd> +</dl> + +<h3>Producers</h3> +.. + +<h3>Visual novel relations</h3> +.. + + + + + + +[[ } # P R O D U C E R A D D / E D I T + if($d{p} == 4) { ]] + +<p> + <i>When to add a producer and what to do with producer relations...</i> +</p> + +<h3>General info</h3> +<dl> + <dt>*Type</dt><dd> + .. + </dd><dt>*Name (romaji)</dt><dd> + .. + </dd><dt>Original name</dt><dd> + .. + </dd><dt>*Primary language</dt><dd> + .. + </dd><dt>Website</dt><dd> + .. + </dd><dt>Description</dt><dd> + .. + </dd> +</dl> + + + + +[[ } # G E N E R A L G U I D E L I N E S + if($d{p} == 5) { ]] + + +Misc documentation:<br /> +- Romanisation and capitalization (http://wiki.anidb.net/w/Romanisation)<br /> +- What to do with fandisks<br /> +- Edit summary<br /> +- Quoting sources in descriptions<br /> +- Piracy<br /> +- Spoilers<br /> + + + + +[[ } # N O S P A M M E S S A G E + if($d{p} == 6) { ]] + +<span class="warning"> + <b>Error:</b> The form could not be sent, please make sure you have Javascript + enabled in your browser! +</span> + + +[[ } ]] +</div> diff --git a/data/tpl/error b/data/tpl/error new file mode 100644 index 00000000..76bd9462 --- /dev/null +++ b/data/tpl/error @@ -0,0 +1,45 @@ +<head> + <title> + [[ if($X->{error}->{code} == 1) { ]]VNDB offline + [[ } else { ]] ERROR: [[= $X->{error}->{code} ]][[ } ]] + </title> + + <meta name="Robots" content="index, follow" /> + <link href="/favicon.ico" type="image/x-icon" rel="shortcut icon" /> + + <style type="text/css"> + body { background-color: #e0e0e0; padding: 0px; text-align: center; font-family: "Arial", Sans-serif; font-size: 11px; line-height: 16px; font-weight: normal; color: #242424; } + #wrapper { margin: 0px auto; margin-bottom: 20px; background-color: #fff; text-align: center; width: 672px; border: 1px solid #b8b8b8; } + #pre { background-color: #fff; text-align: left; padding: 0px 10px 5px 10px; margin: 5px 5px 5px 5px; border: 1px solid #e9e9e9; } + p { font-size: 11px; color: #242424; text-align: justify; padding-left: 17px; padding-right: 17px; } + h1 { font-size: 16px; font-weight: bold; color: #242424; padding-left: 17px; } + a { color: #33659E; text-decoration: none; } + a:hover { text-decoration: underline; } + img { border: 0; margin: 0; padding: 0; } + [[ if($X->{error}->{code} == 500) { ]] + #wrapper { width: 530px; } + [[ } ]] + </style> +</head> +<body> + <div id="wrapper"> + <div id="pre"> + [[ if($X->{error}->{code} > 300 && $X->{error}->{code} < 310) { ]] + <h1>Moved</h1> + <p> + Check <a href="[[% $X->{error}->{url} ]]">[[: $X->{error}->{url} ]]</a> for the new location. + </p> + [[ } elsif($X->{error}->{code} == 401) { ]] + <h1>Login required</h1> + <p> + <a href="/">Please login</a> + </p> + [[ } elsif($X->{error}->{code} == 1) { ]] + <h1>VNDB offline</h1> + <p> + [[: $X->{error}->{msg} ]] + </p> + [[ } ]] + </div> + </div> +</body> diff --git a/data/tpl/faq b/data/tpl/faq new file mode 100644 index 00000000..1c64056e --- /dev/null +++ b/data/tpl/faq @@ -0,0 +1,75 @@ +<h2>[[: $p{PageTitle} ]]</h2> +<br /> +<h3>What is a Visual Novel?</h3> +<p> + A visual novel can be seen as a combination of a novel and a computer game: + they're computer games with a large text based storyline and only little + interaction of the player. A typical visual novel consists of text over + an anime-style background image and is accompanied by background music. + Throughout the game, the player usually has to answer a few questions which will + have an effect on the story, thus playing a visual novel a second time while + giving other answers may result in an entirely different plot.<br /> + <br /> + For more information see <a href="http://en.wikipedia.org/wiki/Visual_Novel"> + the Wikipedia article on visual novels</a> or the description on + <a href="http://visual-novels.net/vn/index.php?option=com_content&task=view&id=259&Itemid=47">Visual-Novels.net</a>. + To get a general idea of the genre, try one of the free short visual novels from + <a href="http://at2006.haeleth.net/release.php">al|together 2006</a>. + <br /><br /><br /> +</p> + + +<h3>How about Eroge, H-Games and Dating Sims?</h3> +<p> + An eroge or H-game is basically any Japanese game that features sexual + content. Many visual novels are eroge and many eroge are visual novels, + but this is not a rule. The definition of dating sim is a bit more vague, + but it's usually the same as a visual novel, except that a dating sim + generally uses a gameplay based on statistics.<br /> + <br /> + There are no strict bounds to the definition of "visual novel", most + eroge and dating sims include elements of visual novels, but may - + strictly speaking - not be visual novels themselves. As VNDB aims to + be comprehensive, we simply accept any game that contains elements of a + visual novel and is produced by a Japanese or Japan-related company or + doujin cicle. + <br /><br /><br /> +</p> + + +<h3>Why a Visual Novel Database?</h3> +<p> + The internet is large, very large, but the number of English resources + related to visual novels is only very limited. VNDB attempts to collect + and present as much information as possible that would otherwise be very + hard to find for the English speaking audience. This way fans can easily + keep track of new releases and localizations of their favorite games, + while not having to browse numerous of indistinct Japanese websites. + <br /><br /><br /> +</p> + + +<h3>How can I help VNDB?</h3> +</p> + There are many ways to contribute to VNDB. First of all you can freely + edit all information found on this website, so if you find any errors + just click the "edit" link on the top right of the page. You can also + add new information (visual novels, producers, releases) to the database, + though please search the database before you do in order to prevent + duplicate pages.<br /> + <br /> + To discuss about new features or to help the development of the website + itself, feel free to browse the <a href="http://forum.vndb.org/">forums</a> + or join us on IRC at <a href="irc://irc.synirc.net/vndb">#vndb @ irc.synirc.net</a>. + If you aren't used to IRC or are just to lazy to install a client, you can + still join the chat using <a href="http://cgiirc.synirc.net/">the Webchat</a>. + Just choose a nickname, specify #vndb as channel and hit Login! + <br /><br /><br /> +</p> + + +<h3>Where can I download the Visual Novels?</h3> +<p> + Not here. We do not provide downloads nor links to resources that encourage + the illegal spreading of visual novels. +</p> diff --git a/data/tpl/hist b/data/tpl/hist new file mode 100644 index 00000000..e02a149f --- /dev/null +++ b/data/tpl/hist @@ -0,0 +1,103 @@ +[[= $d{type} && $d{type} ne 'u' ? ttabs($d{type}, $d{obj}, 'hist') : '' ]]- +<h2 class="rss">[[: $p{PageTitle} ]]</h2> +[[ if($d{type} eq 'u' && $#{$d{hist}} < 0) { ]] +<p> + You haven't made any changes yet. +</p> +[[ } ]] +<br /><br /> + +[[ + my $url = !$d{type} ? '/hist' : '/'.$d{type}.$d{id}.'/hist'; + my $furl = $url.'?e='.$d{sele}.';t='; + my $eurl = $url.'?t='.$d{selt}.';e='; + my $purl = !$d{type}?$eurl.$d{sele}:$d{type} eq 'v' && $d{seli} ? $url.'?i=1' : $url; + my $rurl = $url.'/rss'.(!$d{type}?'?t='.$d{selt}.';e='.$d{sele}:$d{type} eq 'v' && $d{seli} ? '?i=1' : ''); + local $_ = $d{selt}; + my @fil = ( + /a/ ? 'all items' : '<a href="%sa">all items</a>', + /v/ ? 'visual novels' : '<a href="%sv">visual novels</a>', + /r/ ? 'releases' : '<a href="%sr">releases</a>', + /p/ ? 'producers' : '<a href="%sp">producers</a>', + ); + local $_ = $d{sele}; + my @edi = ( + /0/ ? 'all changes' : '<a href="%s0">all changes</a>', + /2/ ? 'edits only' : '<a href="%s2">edits only</a>', + /1/ ? 'newly created pages only' : '<a href="%s1">newly created pages only</a>', + ); + local $_ = $d{seli}; + my @inc = ( + /0/ ? 'exclude' : '<a href="'.$url.'">exclude</a>', + /1/ ? 'include' : '<a href="'.$url.'?i=1">include</a>', + ); +]] + +[[ if(!$d{type}) { ]]- +<p class="browse"> + [[= join(' | ', map { sprintf $_, $furl } @fil) ]]<br /> + [[= join(' | ', map { sprintf $_, $eurl } @edi) ]]<br /><br /><br /> +</p> +[[ } if($d{type} eq 'v') { ]]- +<p class="browse"> + ([[= join(' | ', @inc) ]]) edits of releases. +</p> +[[ } ]] + +[[ if($d{act} eq 'r') { ]] +<span class="msg"> + Performed the mass-revert, please see the following list for details. +</span> +[[ } elsif($d{act} eq 'd') { ]] +<span class="msg"> + The following edits have been completely deleted. +</span> +[[ } ]]- + + +<a class="rss" href="[[= $rurl ]]">RSS</a> +[[= pagebut($purl) ]] +[[ if(0 and $p{Authmod} || $p{Authdel}) { ]] +<form method="post" action="[[= $purl ]]" class="tblf"> +[[ } ]] +<table id="thi"> + <thead><tr> + <td class="tc1">Rev.</td> + <td class="tc2">Date</td> + [[ if($d{type} ne 'u' || $d{act}) { ]]- + <td class="tc3">User</td>[[ } ]]- + [[ if(!$d{type} || $d{type} eq 'u' || $d{act} || ($d{type} eq 'v' && $d{seli})) { ]]- + <td class="tc4">Page</td>[[ } ]]- + [[ if($d{type} && !$d{act}) { ]]- + <td class="tc5">Summary</td>[[ } ]]- + [[ if($d{act} eq 'r') { ]]- + <td class="tc5">Action</td>[[ } ]]- + [[ if(0 and $p{Authmod}) { ]]- + <td class="tc6"><input type="checkbox" id="checkall" name="sel" value="all" /></td>[[ } ]]- + </tr></thead> + + [[ for (@{$d{hist}}) { my $t = (qw|v r p|)[$_->{type}]; ]]- + <tr> + <td class="tc1"><a href="/[[= $t.$_->{iid} ]]?rev=[[= $_->{id} ]]">[[= $_->{id} ]]</a></td> + <td class="tc2">[[= formatdate('%Y-%m-%d %R', $_->{added}, 'dh') ]]</td> + [[ if($d{type} ne 'u' || $d{act}) { ]]- + <td class="tc3"><a href="/u[[= $_->{requester} ]]">[[: $_->{username} ]]</a></td>[[ } ]]- + [[ if(!$d{type} || $d{type} eq 'u' || $d{act}) { ]]- + <td class="tc4">[[= $_->{prev} ? $t.$_->{iid} : '<b>'.$t.$_->{iid}.'</b>' ]]:<a href="/[[= $t.$_->{iid} ]]?rev=[[= $_->{id} ]]" title="[[: $_->{ititle} ]]">[[: length($_->{ititle}) > 30 ? substr($_->{ititle},0,27).'...' : $_->{ititle} ]]</a></td>[[ } ]]- + [[ if($d{type} eq 'v' && $d{seli}) { ]]- + <td class="tc4"><a href="/[[= $t.$_->{iid} ]]" title="[[: $_->{ititle} ]]">[[= $_->{prev} ? $t.$_->{iid} : '<b>'.$t.$_->{iid}.'</b>' ]]</a></td>[[ } ]]- + [[ if($d{type} && !$d{act}) { ]]- + <td class="tc5">[[= summary($_->{comments}, $d{type} eq 'u' ? 40 : 60)||'[empty]' ]]</td>[[ } ]]- + [[ if($d{act} eq 'r') { ]]- + <td class="tc5">[[: $_->{_status} ]]</td>[[ } ]]- + [[ if(0 and $p{Authmod} && !$d{act}) { ]]- + <td class="tc6"><input type="checkbox" name="sel" value="[[= $_->{id} ]]" /></td>[[ } ]]- + </tr> + [[ } ]] + +</table> +[[ if(0 and $p{Authmod}) { ]]<input type="submit" class="right" name="post" value="Mass revert" />[[ } ]] +[[ if(0 and $p{Authdel}) { ]]<input type="submit" class="right" name="post" value="Mass delete" id="massdel" />[[ } ]] +[[ if(0 and $p{Authmod} || $p{Authdel}) { ]]</form>[[ } ]] +[[= pagebut($purl) ]] + diff --git a/data/tpl/home b/data/tpl/home new file mode 100644 index 00000000..5d8cd763 --- /dev/null +++ b/data/tpl/home @@ -0,0 +1,67 @@ +<h2>Welcome to VNDB - The Visual Novel Database!</h2> +<p class="desc"> + <br /> + VNDB.org strives to be a comprehensive database for information about visual novels and + eroge.<br /> + This website is built as a wiki, meaning that anyone can freely add and contribute information + to the database, allowing us to create the largest, most accurate and most up-to-date visual novel + database on the web.<br /> + Registered users are also able to keep track of a personal list of games they want to play or have finished + and they can vote on all visual novels.<br /><br /> + + Feel free to <a href="/v">browse around</a>, <a href="/u/register">register an account</a> + or to discuss about the database at our <a href="http://forum.vndb.org/">forums</a>. +</p> + +<h3 class="home">VNDB 1.13!</h3> +<p class="desc"> + And it's time for an update again: This update makes it possible to specify how much + a category applies to a visual novel, adds a language filter to the category browser, + and fixes many, many bugs. + <br /> + <a href="http://forum.vndb.org/index.php?topic=43.0">Read more...</a> - <a href="http://forum.vndb.org/index.php?board=7.0">news archive</a>. +</p> + +<ul class="home"> + <li><b>Recent changes</b></li> + [[ for (@{$d{recentedits}}) { my $t = (qw|v r p|)[$_->{type}]; ]]- + <li>[[= $t ]]:<a href="/[[= $t.$_->{iid}.'?rev='.$_->{id} ]]" title="[[: $_->{ititle} ]]">[[: shorten $_->{ititle}, 30 ]]</a></li> + [[ } ]]- +</ul> + +<ul class="home"> + <li><b>Recent votes</b></li> + [[ for (@{$d{recentvotes}}) { ]]- + <li><a href="/v[[= $_->{vid} ]]" title="[[: $_->{title} ]]">[[: shorten $_->{title}, 30 ]]</a> ([[= $_->{vote} ]])</li> + [[ } ]] +</ul> + +<ul class="home"> + <li><b>Most popular</b></li> + [[ for (@{$d{popular}}) { $_->{c_votes} =~ s#^([0-9]{2}.[0-9]{2}).+$#sprintf '%.1f', $1#e; ]]- + <li><a href="/v[[= $_->{id} ]]" title="[[: $_->{title} ]]">[[: shorten $_->{title}, 30 ]]</a> ([[= $_->{c_votes} ]])</li> + [[ } ]] +</ul> + +<ul class="home break"> + <li><b>Recently added visual novels</b></li> + [[ for (@{$d{recentvns}}) { ]]- + <li><a href="/v[[= $_->{iid} ]]" title="[[: $_->{ititle} ]]">[[: shorten $_->{ititle}, 30 ]]</a></li> + [[ } ]]- +</ul> + +<ul class="home"> + <li><b>Recently added producers</b></li> + [[ for (@{$d{recentps}}) { ]]- + <li><a href="/p[[= $_->{iid} ]]" title="[[: $_->{ititle} ]]">[[: shorten $_->{ititle}, 30 ]]</a></li> + [[ } ]]- +</ul> + +<ul class="home"> + <li><b>Random visual novels</b></li> + [[ for (@{$d{randomvns}}) { ]]- + <li><a href="/v[[= $_->{id} ]]" title="[[: $_->{title} ]]">[[: shorten $_->{title}, 30 ]]</a></li> + [[ } ]]- +</ul> + + diff --git a/data/tpl/main b/data/tpl/main new file mode 100644 index 00000000..d52a576a --- /dev/null +++ b/data/tpl/main @@ -0,0 +1,14 @@ +[[+ defs.pl ]] + +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + +-[[ if($X->{error}) { ]] + [[+ error ]] +[[ } if($X->{page}) { %p = %{$X->{page}}; gettitle(); ]] + [[+ page ]] +[[ } ]]- + +</html> diff --git a/data/tpl/myvotes b/data/tpl/myvotes new file mode 100644 index 00000000..9379e98e --- /dev/null +++ b/data/tpl/myvotes @@ -0,0 +1,30 @@ +<h2>[[: $p{PageTitle} ]]</h2> +[[ if($#{$d{votes}} < 0) { ]]- +<p> +[[ if($d{user}{username} eq $p{AuthUsername}) { ]] + You haven't voted on anything yet... +[[ } else { ]] + [[: $d{user}{username} ]]- hasn't voted on anything yet... +[[ } ]] +</p> +[[ } else { + my $url = sprintf '/u%d/votes', $d{user}{id}; + my $surl = sprintf '%s?s=%s&o=%s', $url, $d{order}[0], $d{order}[1]; +]] +[[= pagebut($surl) ]]- +<table id="tmv"> + <thead><tr> + <td class="tc1">Title [[= sortbut($url, 'title') ]]</td> + <td class="tc2">Vote [[= sortbut($url, 'vote') ]]</td> + <td class="tc3">Date [[= sortbut($url, 'date') ]]</td> + </tr></thead> + [[ for (@{$d{votes}}) { ]]- + <tr> + <td class="tc1"><a href="/v[[= $_->{vid} ]]">[[: $_->{title} ]]</a></td> + <td class="tc2">[[: $_->{vote} ]]</td> + <td class="tc3">[[= formatdate('%Y-%m-%d', $_->{date}, 'dh') ]]</td> + </tr> + [[ } ]]- +</table> +-[[= pagebut($surl) ]] +[[ } ]] diff --git a/data/tpl/page b/data/tpl/page new file mode 100644 index 00000000..e6ce9e99 --- /dev/null +++ b/data/tpl/page @@ -0,0 +1,140 @@ +<head> + <title>[[: $p{PageTitle} ]]- :: VNDB</title> + <link href="[[: $p{st} ]]/files/style.css?[[= $VNDB::VERSION ]]" rel="stylesheet" type="text/css" media="screen" /> + <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> +[[ if($p{redit} || $p{vnedit}) { ]]- + <script src="[[: $p{st} ]]/files/dyna.js?[[= $VNDB::VERSION ]]" type="text/javascript"></script> +[[ } ]]- + <script src="[[: $p{st} ]]/files/def.js?[[= $VNDB::VERSION ]]" type="text/javascript"></script> +[[ if($p{devshit}) { ]]- + <meta name="robots" content="noindex, nofollow" /> +[[ } elsif($p{userlist} || $p{userpage} || $p{myvotes} || $p{vnlist} || $p{hist} || ($p{vnpage} && $p{vnpage}{page} eq 'stats') + || grep { $p{$_} && $p{$_}{change} } qw|vnpage ppage rpage|) { ]]- + <meta name="robots" content="noindex, follow" /> +[[ }]]- + +[[if($p{hist}){ ]] + <link rel="alternate" type="application/rss+xml" title="Recent changes" href=" + [[= (!$p{hist}{type}?'/hist':'/'.$p{hist}{type}.$p{hist}{id}.'/hist').'/rss'.(!$p{hist}{type}?'?t='.$p{hist}{selt}.';e='.$p{hist}{sele}:$p{hist}{type} eq 'v' && $p{hist}{seli} ? '?i=1':'') ]]" /> +[[ } ]]- +</head> + +<body> +<div id="header"> + <form id="search" method="get" action="/v/search"> + <fieldset> + <legend>Search</legend> + <input id="searchfield" type="text" name="q" value="[[: $p{searchquery} || 'search' ]]"[[= !$p{searchquery} ? ' style="color: #999"': '' ]]- /> + <input id="searchsubmit" type="submit" value="Search" /> + </fieldset> + </form> + <h1><a href="/">vndb.org</a> / #vndb @ irc.synirc.net <a href="http://vndb.org/"> + [[ if($p{devshit}) { ]]<b style="color: red">The VNDB.org Testing Grounds</b>[[ } else { ]]<b>The Visual Novel Database</b>[[ } ]]</a></h1> +</div> + + +<div id="page"> + +<div id="content"> +[[ # = noindex-tag (see above) ]] +[[ if($p{home}) { %d = %{$p{home}}; ]] [[+ home ]][[ } ]] +[[ if($p{faq}) { %d = %{$p{faq}}; ]] [[+ faq ]][[ } ]] +[[ if($p{userlogin}) { %d = %{$p{userlogin}}; ]] [[+ userlogin ]][[ } ]] +[[ if($p{userreg}) { %d = %{$p{userreg}}; ]] [[+ userreg ]][[ } ]] +[[ if($p{userpass}) { %d = %{$p{userpass}}; ]] [[+ userpass ]][[ } ]] +[[ if($p{useredit}) { %d = %{$p{useredit}}; ]] [[+ useredit ]][[ } ]] +[[ if($p{userlist}) { %d = %{$p{userlist}}; ]] [[+ userlist ]][[ }# ]] +[[ if($p{userpage}) { %d = %{$p{userpage}}; ]] [[+ userpage ]][[ }# ]] +[[ if($p{vnpage}) { %d = %{$p{vnpage}}; ]] [[+ vnpage ]][[ } ]] +[[ if($p{vnedit}) { %d = %{$p{vnedit}}; ]] [[+ vnedit ]][[ } ]] +[[ if($p{redit}) { %d = %{$p{redit}}; ]] [[+ redit ]][[ } ]] +[[ if($p{vnbrowse}) { %d = %{$p{vnbrowse}}; ]] [[+ vnbrowse ]][[ } ]] +[[ if($p{pbrowse}) { %d = %{$p{pbrowse}}; ]] [[+ pbrowse ]][[ } ]] +[[ if($p{pedit}) { %d = %{$p{pedit}}; ]] [[+ pedit ]][[ } ]] +[[ if($p{ppage}) { %d = %{$p{ppage}}; ]] [[+ ppage ]][[ } ]] +[[ if($p{myvotes}) { %d = %{$p{myvotes}}; ]] [[+ myvotes ]][[ }# ]] +[[ if($p{vnlist}) { %d = %{$p{vnlist}}; ]] [[+ vnlist ]][[ }# ]] +[[ if($p{hist}) { %d = %{$p{hist}}; ]] [[+ hist ]][[ }# ]] +[[ if($p{rpage}) { %d = %{$p{rpage}}; ]] [[+ rpage ]][[ } ]] +[[ if($p{docs}) { %d = %{$p{docs}}; ]] [[+ docs ]][[ } ]] +</div> + + +<div id="side"><div><div> + + <h2>Menu</h2> + <ul> + <li><a href="/">Home</a></li> + <li><a href="/v">Visual Novels</a></li> + <li><a href="/p">Producers</a></li> + <li><a href="/v/cat">Categories</a></li> + <li><a href="/u/list">Users</a></li> + <li><a href="/hist">Recent changes</a></li> + <li><a href="/faq">FAQ</a></li> + <li><a href="http://forum.vndb.org/">Forum</a></li> + </ul> + +-[[ if(!$p{AuthLoggedin}) { ]]- + <h2>Login</h2> + <form method="post" action="/nospam?/u/login" id="loginform"> + <fieldset> + <legend>Login</legend> + <input type="text" id="usrname" name="username" /> + <input type="password" id="usrpass" name="userpass" /> + <input type="submit" value="Login" /> + </fieldset> + </form> + <p> + <a href="/u/register">register</a> or <a href="/u/newpass">forgot password?</a> + </p> +[[ } else { ]]- + <h2>User menu</h2> + <ul> + <li>[[: $p{AuthUsername} ]]- ([[: $p{AuthRankname} ]])</li> + <li><a href="/u[[= $p{AuthId} ]]/edit">My profile</a></li> + <li><a href="/u[[= $p{AuthId} ]]/votes">My votes</a></li> + <li><a href="/u[[= $p{AuthId} ]]/list">My visual novel list</a></li> + <li><a href="/u[[= $p{AuthId} ]]/hist">My recent changes</a></li> + [[ if($p{Authedit}) { ]]- + <li> </li> + <li><a href="/v/new">Add visual novel</a></li> + <li><a href="/p/add">Add producer</a></li> + [[ } ]] + <li> </li> + <li><a href="/u/logout">Logout</a></li> + </ul> +[[ } ]]- + +-[[ #</div></div><div><div> ]] + <h2>Statistics</h2> + <ul> + <li><b>[[= $p{Statvn}||0 ]]</b> visual novels</li> + <li><b>[[= $p{Statproducers}||0 ]]</b> producers</li> + <li><b>[[= $p{Statreleases}||0 ]]</b> releases</li> + <li><b>[[= $p{Statvotes}||0 ]]</b> votes</li> + <li><b>[[= $p{Statusers}||0 ]]</b> users</li> + </ul> +[[ if(0) { ]] <h2>Most popular</h2> + <ul>[[ for (@{$p{popular}}) { ]]- + <li><a href="/v[[: $_->{id} ]]" title="[[: $_->{title} ]]">[[: length($_->{title})>30 ? (substr($_->{title}, 0, 27).'...') : $_->{title} ]]</a></li>[[ } ]]- + <li class="more"><a href="/v/all?s=votes&o=d">More...</a></li> + </ul>[[ } ]]- +</div></div></div> + +</div> + +<div id="footer"> + <p> + vndb v[[: $VNDB::VERSION ]]- | + <a href="mailto:contact@vndb.org">contact@vndb.org</a> | + designed by <a href="http://www.freecsstemplates.org/">free css templates</a>. + </p> +</div> + +-[[ if(0 && $p{devshit}) { ]]- + <pre id="debug">SQL Queries used:<br /> +[[= $p{devshit} ]] +</pre> +[[ } ]]- + +</body> diff --git a/data/tpl/pbrowse b/data/tpl/pbrowse new file mode 100644 index 00000000..71b40c82 --- /dev/null +++ b/data/tpl/pbrowse @@ -0,0 +1,45 @@ +<h2>[[: $p{PageTitle} ]]</h2> +<p class="chr"> + -[[= $d{chr} ne 'all' ? '<a href="/p/all">all</a>' : 'all' ]]- | + [[ for('a'..'z', 0) { ]]- + -[[ if($d{chr} eq $_) { ]][[= $_?$_:'#' ]][[ } else { ]]<a href="/p/[[= $_ ]]">[[= $_?$_:'#' ]]</a>[[ } ]] + [[ } ]]- + <form id="psearch" method="get" action="/p" accept-charset="UTF-8"> + <fieldset> + <input type="text" name="q" id="q" value="[[: $d{query} ]]" class="text" /> + <input type="submit" value="Search!" /> + </fieldset> + </form> +</p> + +-[[ if($#{$d{prods}} < 0) { ]] +<p> + No results again, life sucks... :'( +</p> +[[ } else { + my $url = sprintf '/p/%s', $d{chr}; + $url .= '?q='.$d{query} if $d{query}; +]] +[[= pagebut($url) ]] +<table id="tpd"> + <thead><tr> + <td class="tc1">Name</td> + <td class="tc2">Type</td> + <td class="tc3">Main language</td> + <td class="tc4">Website</td> + </tr></thead> +[[ for (@{$d{prods}}) { ]]- + <tr> + <td class="tc1"><a href="/p[[= $_->{id} ]]">[[: $_->{name} ]]</a></td> + <td class="tc2">[[: $VNDB::PROT->{$_->{type}} ]]</td> + <td class="tc3">[[: $VNDB::LANG->{$_->{lang}} ]]</td> + <td class="tc4"> + [[ if($_->{website}) { ]] + <a href="[[: $_->{website} ]]">[[: length($_->{website}) > 30 ? substr($_->{website}, 0, 27).'...' : $_->{website} ]] + [[ } else { ]]---[[ } ]] + </td> + </tr> +[[ } ]]- +</table> +[[= pagebut($url) ]] +[[ } ]] diff --git a/data/tpl/pedit b/data/tpl/pedit new file mode 100644 index 00000000..6ef398cf --- /dev/null +++ b/data/tpl/pedit @@ -0,0 +1,45 @@ +[[= $d{id} ? ttabs('p', $d{prod}, 'edit') : '' ]] +<h2>[[: $p{PageTitle} ]]</h2> +-[[ if(!$d{id}) { ]] + <span class="msg"> + Please search the database before adding a new producer in order to prevent duplicate entries. + </span> +[[ } else { ]] + <span class="msg"> + It is currently not possible to delete producers from the database, please + use the <a href="http://forum.vndb.org/index.php?board=5.0">forums</a> to request + a deletion. Also refer to the forums for more serious edits or discussions about changes. + </span> +[[ } if($d{id} && $d{prod}{cid} != $d{prod}{latest}) { ]] + <span class="warning"> + You are editing an old revision of this producer. If you save it, all changes made after + -[[= formatdate('%Y-%m-%d %R', $d{prod}{added}) ]]- will be removed! + </span> +[[ } ]] + +-[[= cform([ + { type => 'error' }, + { type => 'startform', action => $d{id} ? '/p'.$d{id}.'/edit' : '/p/add' }, + + { type => 'sub', title => 'General info', short => 'info' }, + { type => 'select', name => 'Type', short => 'type', r=>1, options => [ map { + { short => $_, name => $VNDB::PROT->{$_} } } sort keys %$VNDB::PROT ] }, + { type => 'input', name => 'Name (romaji)', short => 'name', r=>1 }, + { type => 'input', name => 'Original name', short => 'original' }, + { type => 'static', text => q| + The original name of the producer, leave blank if it is already in the Latin alphabet.<br /><br />| }, + + { type => 'select', name => 'Primary language', short => 'lang', r=>1, options => [ map { + ({ short => $_, name => sprintf '%s (%s)', $_, $VNDB::LANG->{$_} }) } sort keys %{$VNDB::LANG} ] }, + + { type => 'input', name => 'Website', short => 'website' }, + { type => 'textarea', name => 'Description', short => 'desc', rows => 7, cols => 60 }, + + { type => 'sub', title => 'Edit summary', short => 'com' }, + { type => 'textarea', name => 'Edit summary', short => 'comm', rows => 3, cols => 60 }, + { type => 'static', text => 'Please motivate your modifications and cite all sources.' }, + + { type => 'submit', text => $d{id} ? 'Edit' : 'Add' }, + { type => 'endform' }, + +], $d{form}) ]] diff --git a/data/tpl/ppage b/data/tpl/ppage new file mode 100644 index 00000000..e829682a --- /dev/null +++ b/data/tpl/ppage @@ -0,0 +1,58 @@ +[[= ttabs('p', $d{prod}) ]] +<h2>[[: $p{PageTitle} ]]</h2> + +[[ if($d{prod}{hidden}) { ]]- + <span class="warning"> + This item has been deleted from the database. File a request on the + <a href="http://forum.vndb.org/index.php?board=5.0">forums</a> + to undelete this page. + </span> +[[ } ]] +[[ if(!$d{prod}{hidden} || $p{Authdel}) { ]]- + + + +[[ if($d{change}) { ]] +[[= cdiff($d{prev}, $d{prod}, + [ type => 'Type', sub { $VNDB::PROT->{$_[0]} } ], + [ name => 'Name (romaji)', 1 ], + [ original => 'Original name', 1 ], + [ lang => 'Language', sub { $VNDB::LANG->{$_[0]} } ], + [ website => 'Website', 1 ], + [ desc => 'Description', 1, 1 ], + ) ]] +[[ } ]] + +<dl> + <dt>Name</dt><dd>[[ if($d{prod}{original}) { ]] + [[: $d{prod}{original} ]]- ([[: $d{prod}{name} ]]) + [[ } else { ]][[: $d{prod}{name} ]][[ } ]]</dd> + <dt>Type</dt><dd>[[: $VNDB::PROT->{$d{prod}{type}} ]]</dd> + <dt>Primary lang.</dt><dd>[[: $VNDB::LANG->{$d{prod}{lang}} ]]</dd> +[[ if($d{prod}{website}) { ]]- + <dt>Links</dt><dd><a href="[[: $d{prod}{website} ]]">Official homepage</a></dd>[[ } ]]- +</dl> + +-[[ if($d{prod}{desc}) { ]] +<p>[[= summary($d{prod}{desc}) ]]<br /><br /></p> +[[ } ]] + + +<h3>Visual novel relations</h3> +[[ if($#{$d{vn}} < 0) { ]]- +<p> + We have currently no visual novels related to this producer. +</p> +[[ } else { ]]- +<ul> + [[ for (@{$d{vn}}) { ]]- + <li><a href="/v[[= $_->{id} ]]">[[: $_->{title} ]]</a> + [[ if($_->{date} ne "0000-00-00") { ]]- ([[= datestr($_->{date}) ]])[[ } ]] + </li> + [[ } ]]- +</ul> +[[ } ]] + + + +[[ } ]] diff --git a/data/tpl/redit b/data/tpl/redit new file mode 100644 index 00000000..0e83b670 --- /dev/null +++ b/data/tpl/redit @@ -0,0 +1,70 @@ +[[= $d{id} ? ttabs('r', $d{rel}, 'edit') : ttabs('v', $d{vn}, 'edit') ]]- +<h2>[[: $p{PageTitle} ]]</h2> + +[[ if($d{id}) { ]] + <span class="msg"> + It is currently not possible to delete releases from the database, please + use the <a href="http://forum.vndb.org/index.php?board=5.0">forums</a> to request + a deletion. Also refer to the forums for more serious edits or discussions about changes. + </span> +[[ } if($d{id} && $d{rel}{cid} != $d{rel}{latest}) { ]] + <span class="warning"> + You are editing an old revision of this producer. If you save it, all changes made after + -[[= formatdate('%Y-%m-%d %R', $d{rel}{added}) ]]- will be removed! + </span> +[[ } ]] + +[[= cform( [ + { type => 'error' }, + { type => 'startform', action => $d{id} ? sprintf('/r%d/edit', $d{rel}{id}) : '/v'.$d{vn}{id}.'/add', fh => 1 }, + + { type => 'sub', title => 'General info', short => 'info' }, + { type => 'select', name => 'Type', short => 'type', r=>1, options => [ map { + ({ short => $_, name => $VNDB::RTYP->[$_] }) } 0..$#{$VNDB::RTYP} ] }, + + { type => 'input', name => 'Title (romaji)', short => 'title', r=>1 }, + { type => 'input', name => 'Original title', short => 'original' }, + { type => 'static', text => q| + The original title of this release, leave blank if it already is in the Latin alphabet.<br /><br />| }, + + { type => 'select', name => 'Language', short => 'language', r=>1, options => [ map { + ({ short => $_, name => sprintf '%s (%s)', $_, $VNDB::LANG->{$_} }) } sort keys %{$VNDB::LANG} ] }, + + { type => 'input', name => 'Official website', short => 'website' }, + { type => 'date', name => 'Release date', short => 'released' }, + { type => 'static', text => 'Leave month or day blank if they are unknown<br /><br />' }, + { type => 'select', name => 'Age rating', short => 'minage', options => [ map + { { name => $VNDB::VRAGES->{$_}, short => $_ } } sort { $a <=> $b } keys %$VNDB::VRAGES ] }, + { type => 'textarea', name => 'Notes', short => 'notes', rows => 3, cols => 50 }, + { type => 'static', text => 'Miscellaneous notes/comments, information that does not fit in the above fields. E.g.: Censored/uncensored or for which releases this patch applies. Max. 250 characters.' }, + + { type => 'sub', title => 'Platforms & Media', short => 'pnm' }, + { type => 'static', raw => 1, text => '<label>Platforms</label><ul class="platforms">'.join('', map { my $p = $_; + '<li><input type="checkbox" name="platforms" value="'.$_.'" id="'.$_.'" '. + (($d{form}{platforms} && grep { $p eq $_ } @{$d{form}{platforms}}) ? 'checked="checked" ':'').'/>'. + '<acronym class="plat '.$_.'" title="'.$VNDB::PLAT->{$_}.'">'.$_.'</acronym>'. + '<label for="'.$_.'">'.$VNDB::PLAT->{$_}.'</label></li>' + } sort { $VNDB::PLAT->{$a} cmp $VNDB::PLAT->{$b} } keys %$VNDB::PLAT).'</ul>' }, + + { type => 'static', text => '<br />' }, + { type => 'jssel', name => 'Media', sh => 'md', short => 'media' }, + + { type => 'sub', title => 'Producers', short => 'prod' }, + { type => 'jssel', name => 'Producers', sh => 'pd', short => 'producers' }, + + { type => 'sub', title => 'Visual novel relations', short => 'rel'}, + { type => 'jssel', name => 'Relations', sh => 'vn', short => 'vn', r=>1 }, + { type => 'static', text => q| + Although a release usually contains only one visual novel, it is also possible + for one release to include several games. Use this field to specify which + visual novels are included in this release.| }, + + + { type => 'sub', title => 'Edit summary', short => 'com' }, + { type => 'textarea', name => 'Edit summary', short => 'comm', rows => 3, cols => 60 }, + { type => 'static', text => 'Please motivate your modifications and cite all sources.' }, + + { type => 'submit', text => $d{id} ? 'Edit' : 'Add' }, + { type => 'endform' }, + +], $d{form}) ]] diff --git a/data/tpl/rpage b/data/tpl/rpage new file mode 100644 index 00000000..7ad3c4ea --- /dev/null +++ b/data/tpl/rpage @@ -0,0 +1,61 @@ +[[= ttabs('r', $d{rel}) ]] +<h2>[[: $p{PageTitle} ]]</h2> + +[[ if($d{rel}{hidden}) { ]]- + <span class="warning"> + This item has been deleted from the database. File a request on the + <a href="http://forum.vndb.org/index.php?board=5.0">forums</a> + to undelete this page. + </span> +[[ } ]] +[[ if(!$d{rel}{hidden} || $p{Authdel}) { ]]- + + + +[[ if($d{change}) { ]] +[[= cdiff($d{prev}, $d{rel}, + [ vn => 'Relations', sub { join("<br />\n", map { $_->{title} } @{$_[0]}) } ], + [ type => 'Type', sub { $VNDB::RTYP->[$_[0] ] } ], + [ title => 'Title', 1 ], + [ original => 'Orig. title', 1 ], + [ language => 'Language', sub { $VNDB::LANG->{$_[0]} } ], + [ website => 'Website', \&summary ], + [ released => 'Release date', \&datestr ], + [ minage => 'Age rating', sub { $VNDB::VRAGES->{$_[0]} } ], + [ notes => 'Notes', 1 ], + [ platforms => 'Platforms', sub { join(', ', sort @{$_[0]}) } ], + [ media => 'Media', \&mediastr ], + [ producers => 'Producers', sub { join(', ', map { _hchar($_->{name}) } sort { $a->{name} cmp $b->{name} } @{$_[0]}) } ], + ) ]] +[[ } ]] + +<dl> + <dt>Relation</dt><dd>[[= join('<br />', map { '<a href="/v'.$_->{vid}.'">'._hchar($_->{title}).'</a>' } @{$d{rel}{vn}}) ]]</dd> + <dt>Type</dt><dd>[[: $VNDB::RTYP->[$d{rel}{type}] ]]</dd> + <dt>Title</dt><dd>[[: $d{rel}{title} ]]</dd> +[[ if($d{rel}{original}) { ]]- + <dt>Original Title</dt><dd>[[: $d{rel}{original} ]]</dd>[[ } ]]- + <dt>Language</dt><dd>[[: $VNDB::LANG->{$d{rel}{language}} ]]</dd> + <dt>Release date</dt><dd>[[= datestr($d{rel}{released}) ]]</dd> +[[ if($d{rel}{minage} >= 0) { ]]- + <dt>Age rating</dt><dd>[[: $VNDB::VRAGES->{$d{rel}{minage}} ]]</dd>[[ } ]]- +[[ if($#{$d{rel}{producers}} >= 0) { ]]- + <dt>Producer[[: $#{$d{rel}{producers}} > 0 ? 's' : '' ]]</dt><dd>[[= join(', ', map { + sprintf('<a href="/p%d">%s</a>', $_->{id}, _hchar($_->{name})) } @{$d{rel}{producers}}) + ]]</dd>[[ } ]]- +[[ if($#{$d{rel}{platforms}} >= 0) { ]]- + <dt>Platform[[: $#{$d{rel}{platforms}} > 0 ? 's' : '' ]]</dt><dd>[[: join(', ', map { + $VNDB::PLAT->{$_} } @{$d{rel}{platforms}}) ]]</dd>[[ } ]]- +[[ if($#{$d{rel}{media}} >= 0) { ]]- + <dt>Medi[[: $#{$d{rel}{media}} > 0 ? 'a' : 'um' ]]</dt><dd>[[: mediastr($d{rel}{media}) ]]</dd>[[ } ]]- +[[ if($d{rel}{website}) { ]]- + <dt>Links</dt><dd><a href="[[: $d{rel}{website} ]]">Official website</a></dd>[[ } ]]- +</dl> + +[[ if($d{rel}{notes}) { ]]- +<p>[[= summary($d{rel}{notes}) ]]<br /><br /></p> +[[ } ]]- + + + +[[ } ]] diff --git a/data/tpl/useredit b/data/tpl/useredit new file mode 100644 index 00000000..f470ce0a --- /dev/null +++ b/data/tpl/useredit @@ -0,0 +1,34 @@ +<h2>[[: $p{PageTitle} ]]</h2> + +-[[ if($d{done}) { ]] +<span class="msg"> + Settings succesfully saved. +</span> +[[ } ]] +-[[= cform( [ + { type => 'error' }, + { type => 'startform', action => '/u'.$d{user}.'/edit' }, + + { type => 'sub', title => 'General info', short => 'info' }, + { type => 'static', name => 'Username', text => _hchar($d{form}{username}) }, + { type => 'input', name => 'Email', short => 'mail' }, + + { type => 'sub', title => 'Change password', short => 'pass' }, + { type => 'static', text => 'Leave blank to keep your current password.' }, + { type => 'pass', name => 'Password', short => 'pass1' }, + { type => 'pass', name => 'Confirm', short => 'pass2' }, + + { type => 'sub', title => 'Miscellaneous options', short => 'misc' }, + { type => 'check', short => 'pvotes', name => sprintf 'Allow other people to see my votes (<a href="/u%d/votes">/u%1$d/votes</a>)', $d{user} }, + { type => 'check', short => 'plist', name => sprintf 'Allow other people to see my visual novel list (<a href="/u%d/list">/u%1$d/list</a>)', $d{user} }, + { type => 'check', short => 'pign_nsfw', name => 'Disable warnings for images that are not safe for work.' }, + + $d{adm} ? ( + { type => 'sub', title => 'Admin', short => 'adm' }, + { type => 'select', name => 'Rank', short => 'rank', options => [ + map { { name => $VNDB::VNDBopts{ranks}[0][0][$_], short => $_ } } 1..($#{$VNDB::VNDBopts{ranks}}-1) ] }, + ) : (), + + { type => 'submit', text => 'Save' }, + { type => 'endform' }, +], $d{form}) ]] diff --git a/data/tpl/userlist b/data/tpl/userlist new file mode 100644 index 00000000..4fcb12c7 --- /dev/null +++ b/data/tpl/userlist @@ -0,0 +1,54 @@ +<h2>[[: $p{PageTitle} ]]</h2> +<p class="chr"> + -[[= $d{chr} ne 'all' ? '<a href="/u/list/all">all</a>' : 'all' ]]- | + [[ for('a'..'z', 0) { ]]- + -[[ if($d{chr} eq $_) { ]][[= $_?$_:'#' ]][[ } else { ]]<a href="/u/list/[[= $_ ]]">[[= $_?$_:'#' ]]</a>[[ } ]] + [[ } ]]- + <br /><br /> +</p> + +[[ if($#{$d{users}} < 0) { ]]- +<p> + No users found... +</p> +[[ } else { + my $url = sprintf '/u/list/%s', $d{chr}; + my $surl = sprintf '%s?s=%s&o=%s', $url, $d{order}[0], $d{order}[1]; +]] +[[= pagebut($surl) ]]- +<table id="tul"> + <thead><tr> + <td class="tc1">Username [[= sortbut($url, 'username') ]]</td> +[[ if($p{Authuserlist}) { ]]- + <td class="tc2">Mail [[= sortbut($url, 'mail') ]]</td> + <td class="tc3">Rank [[= sortbut($url, 'rank') ]]</td>[[ } ]]- + <td class="tc4">Registered [[= sortbut($url, 'registered') ]]</td> + <td class="tc5">VN list</td> + <td class="tc6">Votes</td> + <td class="tc7">Changes</td> +[[ if($p{Authuseredit}) { ]]- + <td class="tc8"> </td>[[ } ]]- + </tr></thead> + [[ for (@{$d{users}}) { ]]- + <tr> + <td class="tc1"><a href="/u[[= $_->{id} ]]">[[: $_->{username} ]]</a></td> +[[ if($p{Authuserlist}) { ]]- + <td class="tc2">[[: $_->{mail} ]]</td> + <td class="tc3">[[: $VNDB::VNDBopts{ranks}[0][0][$_->{rank}] ]]</td>[[ } ]]- + <td class="tc4">[[= formatdate('%Y-%m-%d', $_->{registered}, 'wd') ]]</td> + <td class="tc5">[[ if($_->{flags} & $VNDB::UFLAGS->{list} && $_->{vnlist}) { ]] + <a href="/u[[= $_->{id} ]]/list" title="[[: $_->{username} ]]'s visual novel list">[[= $_->{vnlist} ]]</a> + [[ } else { ]][[= $_->{flags} & $VNDB::UFLAGS->{list} ? 0 : '-' ]][[ } ]]</td> + <td class="tc6">[[ if($_->{flags} & $VNDB::UFLAGS->{votes} && $_->{votes}) { ]] + <a href="/u[[= $_->{id} ]]/votes" title="[[: $_->{username} ]]'s votes">[[= $_->{votes} ]]</a> + [[ } else { ]][[= $_->{flags} & $VNDB::UFLAGS->{votes} ? 0 : '-' ]][[ } ]]</td> + <td class="tc7">[[ if($_->{changes}) { ]] + <a href="/u[[= $_->{id} ]]/hist" title="Recent changes by -[[: $_->{username} ]]">[[= $_->{changes} ]]</a> + [[ } else { ]]0[[ } ]]</td> +[[ if($p{Authuseredit}) { ]]- + <td class="tc8">( <a href="/u[[= $_->{id} ]]/edit">edit</a> )</td>[[ } ]]- + </tr> + [[ } ]]- +</table> +-[[= pagebut($surl) ]]- +[[ } ]] diff --git a/data/tpl/userlogin b/data/tpl/userlogin new file mode 100644 index 00000000..b4af29d2 --- /dev/null +++ b/data/tpl/userlogin @@ -0,0 +1,14 @@ +<h2>[[: $p{PageTitle} ]]</h2> +-[[= cform( [ + { type => 'error' }, + { type => 'startform', action => '/u/login' }, + { type => 'input', short => 'username', name => 'Username' }, + { type => 'pass', short => 'userpass', name => 'Password' }, + { type => 'submit', text => 'Login!' }, + { type => 'endform' }, +], $d{log}) ]]- + +<p> + <br /><br /> + <a href="/u/register">No account yet</a>, or <a href="/u/newpass">forgot your username or password?</a> +</p> diff --git a/data/tpl/userpage b/data/tpl/userpage new file mode 100644 index 00000000..9b14efc9 --- /dev/null +++ b/data/tpl/userpage @@ -0,0 +1,13 @@ +[[ + ($d{pv}, $d{pl}) = ($d{user}{flags} & $VNDB::UFLAGS->{votes}, $d{user}{flags} & $VNDB::UFLAGS->{list}); +]] +<h2>[[: $p{PageTitle} ]]</h2> +<dl> + <dt>Username</dt><dd>[[: $d{user}{username} ]]- (<a href="/u[[= $d{user}{id} ]]">u[[= $d{user}{id} ]]</a>)</dd> + <dt>Registered</dt><dd>[[= formatdate('%Y-%m-%d', $d{user}{registered}) ]]</dd> + <dt>Votes</dt><dd>[[= $d{pv} ? $d{user}{votes}.' (<a href="/u'.$d{user}{id}.'/votes">view all</a>)' : '(hidden)' ]]</dd> + <dt>VN List</dt><dd>[[= $d{pl} ? $d{user}{vnlist}.' (<a href="/u'.$d{user}{id}.'/list">view all</a>)' : '(hidden)' ]]</dd> + <dt>Changes</dt><dd>[[= $d{user}{changes}.($d{user}{changes}>0?' (<a href="/u'.$d{user}{id}.'/hist">recent changes</a>)':'') ]]</dd> +</dl> + +[[= T_vnpage_stats($X) ]] diff --git a/data/tpl/userpass b/data/tpl/userpass new file mode 100644 index 00000000..c3b04840 --- /dev/null +++ b/data/tpl/userpass @@ -0,0 +1,21 @@ +<h2>[[: $p{PageTitle} ]]</h2> +<p> + You're lucky that vndb has a very advanced password recovery tool! Just + type your email address (the same one you used for your account), and + wait for an email! +</p> + +-[[ if(!$d{done}) { ]] +[[= cform( [ + { type => 'error', }, + { type => 'startform', action => '/u/newpass' }, + { type => 'input', short => 'mail', name => 'Email' }, + { type => 'submit', text => 'Gimme my password!' }, + { type => 'endform' }, +], $d{pas} ) ]] + +[[ } else { ]] +<span class="msg"> + Your password succesfully been reset. Check your mail for instructions. +</span> +[[ } ]] diff --git a/data/tpl/userreg b/data/tpl/userreg new file mode 100644 index 00000000..68565470 --- /dev/null +++ b/data/tpl/userreg @@ -0,0 +1,38 @@ +<h2>[[: $p{PageTitle} ]]</h2> + +-[[ if($d{denied}) { ]] +[[ } ]]- + +<br /><br /> +<h3>Why should I register?</h3> +<p> + Registered users have access to special features on this site: +</p> +<ul> + <li>You can keep track of the visual novels you'd like to play or have + finnished playing,</li> + <li>Vote on visual novels,</li> + <li>And more importantly: you can add and edit all information on the + website!</li> +</ul> +<p> + <br /> + And of course, registering an account is (and will always remain) + completely free! + <br /><br /> +</p> + +-[[= cform( [ + { type => 'error' }, + { type => 'startform', action => '/u/register' }, + { type => 'input', short => 'username', name => 'Username' }, + { type => 'input', short => 'mail', name => 'Email' }, + { type => 'static', text => q| + Your email address will only be used in case you lose your password, at least for now. + We will never send spam or newsletters unless you explicitly ask us for it. + | }, + { type => 'pass', short => 'pass1', name => 'Password' }, + { type => 'pass', short => 'pass2', name => 'Confirm pass.' }, + { type => 'submit', text => 'Register!' }, + { type => 'endform' }, +], $d{reg}) ]] diff --git a/data/tpl/vnbrowse b/data/tpl/vnbrowse new file mode 100644 index 00000000..79dd122e --- /dev/null +++ b/data/tpl/vnbrowse @@ -0,0 +1,87 @@ +<h2>[[: $p{PageTitle} ]]</h2> + +[[ if($d{chr} eq 'cat') { ]]- +<ul id="cat"> +[[ for my $c (qw| e g p t l s |) { ]]- + -[[= $c ne 'l' && $c ne 'p' ? '<li>' : '<br />' ]][[: $VNDB::CAT->{$c}[0] ]]- + <ul> + [[ for (sort keys %{$VNDB::CAT->{$c}[1]}) { ]]- + <li class="cat_[[= $c.$_ ]][[= $d{incl} =~ /$c$_/ ? ' inc' : $d{excl} =~ /$c$_/ ? ' exc' : '' ]]"> + [[: $VNDB::CAT->{$c}[1]{$_} ]]- ([[= $d{cat}{$c.$_} || 0 ]])</li> + [[ } ]] + </ul>[[= $c ne 't' && $c ne 'g' ? '</li>' : '' ]]- +[[ } ]]- +</ul> +<div id="lfilter"> + <b>Languages</b> (none selected means all)<br /> +[[ for (sort keys %{$d{lang}}) { next if !$d{lang}{$_}; ]]- + <input type="checkbox" name="lang_[[= $_ ]]" id="lang_[[= $_ ]]" value="1" -[[= $d{slang}=~/$_/?'checked="checked"':'' ]]> + <label for="lang_[[= $_ ]]">[[: $VNDB::LANG->{$_} ]]- ([[= $d{lang}{$_} ]])</label> +[[ } ]]- +</div> +<br style="clear: left" /> +<input type="button" class="right" id="catsearch" name="catsearch" value="Search!" /> +<br style="clear: left" /> +<br /> +<br /> + +[[ } elsif($d{chr} ne 'search') { ]]- +<p class="chr"> + -[[= $d{chr} ne 'all' ? '<a href="/v/all">all</a>' : 'all' ]]- | + [[ for('a'..'z', 0) { ]]- + -[[ if($d{chr} eq $_) { ]][[= $_?$_:'#' ]][[ } else { ]]<a href="/v/[[= $_ ]]">[[= $_?$_:'#' ]]</a>[[ } ]] + [[ } ]]- + <br /><br /> +</p> +[[ } ]]- + +-[[ if($#{$d{vn}} < 0) { ]] +<p> + -[[ if($d{chr} eq 'cat' && !$d{scat}[0][0] && !$d{scat}[0][1]) { ]] + Select some categories and hit the "Search" button to get a list of visual novels. Click on a + category again to exclude it.<br /> + Please keep in mind that not all visual novels have the correct categories set, so you + may not always find what you are looking for. + [[ } else { ]] + No results again, life sucks... :'( + [[ } ]]- +</p> +[[ } else { + my %url = ( + $p{searchquery} ? ( q => $p{searchquery} ) : (), + $d{incl} ? ( i => $d{incl} ) : (), + $d{excl} ? ( e => $d{excl} ) : (), + $d{slang} ? ( l => $d{slang} ) : (), + ); + my %urls = ( %url, + $d{order}[0] ne 'title' ? ( s => $d{order}[0] ) : (), + $d{order}[1] ne 'a' ? ( o => $d{order}[1] ) : (), + ); + my $url = sprintf '/v/%s', $d{chr}; + my $urls = $url; + $urls .= '?'.join(';', map { $_.'='.$urls{$_} } keys %urls) if keys %urls; + $url .= '?'.join(';', map { $_.'='.$url{$_} } keys %url) if keys %url; +]] + +[[= pagebut($urls) ]] +<table id="tbv"> + <thead><tr> + <td class="tc1">Title [[= sortbut($url, 'title') ]]</td> + <td class="tc2">Released [[= sortbut($url, 'released') ]]</td> + <td class="tc3">Languages</td> + <td class="tc4">Rating [[= sortbut($url, 'votes') ]]</td> + </thead></tr> + [[ for (@{$d{vn}}) { + $_->{c_votes} =~ s#^([0-9]{2}.[0-9]{2})\|([0-9]{4})$#$1 == 0 ? sprintf '- (%d)', $2 : sprintf '%.2f (%d)', $1, $2#e; + $_->{c_released} =~ s#^([0-9]{4})([0-9]{2}).+#$1==0?'N/A':$1==9999?'TBA':(($2&&$2>0?($Time::CTime::MoY[$2-1].' '):'').$1)#e; + ]]- + <tr> + <td class="tc1"><a href="/v[[= $_->{id} ]]">[[: $_->{title} ]]</a></td> + <td class="tc2">[[: $_->{c_released} ]]</td> + <td class="tc3">[[: $_->{c_languages} || 'N/A' ]]</td> + <td class="tc4">[[: $_->{c_votes} ]]</td> + </tr> + [[ } ]]- +</table> +[[= pagebut($urls) ]] +[[ } ]] diff --git a/data/tpl/vnedit b/data/tpl/vnedit new file mode 100644 index 00000000..f3ae245c --- /dev/null +++ b/data/tpl/vnedit @@ -0,0 +1,94 @@ +[[= $d{id} ? ttabs('v', $d{vn}, 'edit') : '' ]]- +<h2>[[: $p{PageTitle} ]]</h2> + +[[ if(!$d{id}) { ]] + <span class="msg">Please search the database before adding a new visual novel + in order to prevent duplicate entries.</span> +[[ } else { ]] + <span class="msg"> + It is currently not possible to delete visual novels from the database, please + use the <a href="http://forum.vndb.org/index.php?board=5.0">forums</a> to request + a deletion. Also refer to the forums for more serious edits or discussions about changes. + </span> +[[ } if($d{id} && $d{vn}{cid} != $d{vn}{latest}) { ]] + <span class="warning"> + You are editing an old revision of this producer. If you save it, all changes made after + -[[= formatdate('%Y-%m-%d %R', $d{vn}{added}) ]]- will be removed! + </span> +[[ } ]] + + +-[[= cform([ + { type => 'error' }, + { type => 'startform', action => $d{id} ?( '/v'.$d{id}.'/edit') : '/v/new', upload => 1, fh => 1 }, + + { type => 'sub', title => 'General info', short => 'info' }, + { type => 'input', name => 'Title', short => 'title', r=>1 }, + { type => 'static', text => q| + Use official English title if available, use the romanized version of the official title otherwise. + Other titles can be added at a later time when specifying releases.<br /><br />| }, + + { type => 'textarea', name => 'Aliases', short => 'alias', rows => 2, cols => 60 }, + { type => 'static', text => q| + Comma seperated list of alternative titles or abbreviations. Can include both official + (japanese/english) titles and unofficial titles used around net. <b>Titles that are listed in the releases do not have to be added here.</b><br /><br />| }, + + { type => 'textarea', name => 'Description', short => 'desc', rows => 7, cols => 70, r=>1 }, + { type => 'static', text => q| + Short description of the main story. Please do not include spoilers, and don't forget to list the source + in case you didn't write the description yourself. ([url] BBCode tag is allowed)<br /><br />| }, + + { type => 'select', name => 'Length', short => 'length', class => 'longopts', options => [ map { + { short => $_, + name => !$_?$VNDB::VNLEN->[$_][0]:($VNDB::VNLEN->[$_][0].', '.$VNDB::VNLEN->[$_][1].' ('.$VNDB::VNLEN->[$_][2].')') } } 0..$#$VNDB::VNLEN + ] }, + { type => 'static', text => '<br />' }, + { type => 'input', name => 'External links', short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' }, + { type => 'input', name => ' ', short => 'l_vnn', pre => 'http://visual-novels.net/vn/index.php?option=com_content&task=view&id=', class => 'shortopts' }, + { type => 'input', name => ' ', short => 'l_cisv', pre => 'http://cisvisual.net/title/', class => 'shortopts' }, + + { type => 'sub', title => 'Categories', short => 'cat' }, + { type => 'hidden', short => 'categories' }, + { type => 'static', raw => 1, text => eval { + my $r = '<ul id="cat">'; + for my $c (qw| e g p t l s |) { + $r .= ($c ne 'l' && $c ne 'p' ? '<li>' : '<br />').$VNDB::CAT->{$c}[0].'<ul>'; + for (sort keys %{$VNDB::CAT->{$c}[1]}) { + $r .= sprintf '<li><a href="#" id="cat_%1$s"><b id="b_%1$s">-</b> %2$s</a></li>', + $c.$_, $VNDB::CAT->{$c}[1]{$_}; + } + $r .= '</ul>'.($c ne 't' && $c ne 'g' ? '</li>' : ''); + } + $r.'</ul>'; + } }, + + { type => 'sub', title => 'Image', short => 'img' }, + $d{id} ? ( + { type => 'static', text => $d{vn}{image} ? + sprintf '<img src="%s/cv/%02d/%d.jpg" style="float: right" />', $p{st}, $d{vn}{image}%50, $d{vn}{image} : + 'No image uploaded yet...' }, + ) : (), + { type => 'upload', name => $d{vn}{image} ? 'Change' : 'Upload', short => 'img' }, + { type => 'static', text => q| + Preferably the cover of the CD/DVD/package. Image must be in JPEG format and at most 256x400px and 50KB.<br /><br />| }, + { type => 'check', short => 'img_nsfw', name => '<b>NSFW.</b> Please check this option if the image contains nudity, gore, or is otherwise not safe in a work-friendly environment.' }, + + { type => 'sub', title => 'Visual novel relations', short => 'rel' }, + { type => 'jssel', name => 'Relations', short => 'relations', sh => 'rl' }, + { type => 'static', text => q| + <b>Direct relations:</b> Please only add direct relations. E.g. the sequel of a sequel does not have to be listed + here because it's already listed on an other visual novel that is in turn listed here. VNDB will handle these + relations automatically.<br /> + <b>Reverse relations:</b> If you add a relation with an other visual novel here, the same (or "reverse") relation + will automatically be added to the other visual novel. For example: if you add Tsukihime as a prequel of Kagetsu Tohya, + Kagetsu Tohya will automatically be added as a sequel for Tsukihime. + |}, + + { type => 'sub', title => 'Edit summary', short => 'com' }, + { type => 'textarea', name => 'Edit summary', short => 'comm', rows => 3, cols => 60 }, + { type => 'static', text => 'Please motivate your modifications and cite all sources.' }, + + { type => 'submit', text => $d{id} ? 'Edit' : 'Add' }, + { type => 'endform' }, + +], $d{form}) ]] diff --git a/data/tpl/vnlist b/data/tpl/vnlist new file mode 100644 index 00000000..64db1c05 --- /dev/null +++ b/data/tpl/vnlist @@ -0,0 +1,74 @@ +<h2>[[: $p{PageTitle} ]]</h2> +[[ + my $url = sprintf '/u%d/list', $d{user}{id}; + my $surl = sprintf '%s?s=%s;o=%s', $url, $d{order}[0], $d{order}[1]; + my $purl = $surl . ';t='.$d{status}; + my $sourl = $url . '?t='.$d{status}; + my $furl = $purl . ';p='.$d{page}; +]] +<p class="chr"> + status: -[[ for (-1..$#$VNDB::LSTAT) { if($_ >= 0) { ]]- | -[[ } + if($d{status} == $_) { ]]<b>[[= $_ eq -1 ? 'all' : lc $VNDB::LSTAT->[$_] ]]</b>[[ } + else { ]]<a href="[[= $surl ]]&t=[[= $_ ]]">[[= $_ eq -1 ? 'all' : lc $VNDB::LSTAT->[$_] ]]</a>[[ } } ]] + <br /><br /> +</p> + + +[[ if($#{$d{list}} < 0) { ]]- +<p> +[[ if($d{status} >= 0) { ]] + No results found... +[[ } elsif($d{user}{username} eq $p{AuthUsername}) { ]] + Your visual novel list is empty. You can keep track of all the visual novels + you'd like to play, you're currently playing, or you've finished. Just go to + a visual novel page and add it to your VN list! +[[ } else { ]] + [[: $d{user}{username} ]]'s visual novel list is empty... +[[ } ]] +</p> + +[[ } else { ]] +[[= pagebut($purl) ]]- +[[ if($d{user}{username} eq $p{AuthUsername}) { ]] +<form method="post" action="[[= $furl ]]" class="tblf"> +<input type="hidden" class="hidden" name="comments" id="comments" value="" />[[ } ]] +<table id="tvl"> + <thead><tr> + <td class="tc1">Title [[= sortbut($sourl, 'title') ]]</td> + <td class="tc2">Status</td> + <td class="tc3">Added [[= sortbut($sourl, 'date') ]]</td> + [[ if($d{user}{username} eq $p{AuthUsername}) { ]]- + <td class="tc4">Personal note</td> + <td class="tc5"> </td>[[ } ]]- + </tr></thead> + [[ for (@{$d{list}}) { ]]- + <tr> + <td class="tc1"><a href="/v[[= $_->{vid} ]]" title="[[: $_->{title} ]]">[[: length($_->{title})>40 ? substr($_->{title},0, 37).'...' : $_->{title} ]]</a></td> + <td class="tc2">[[= $VNDB::LSTAT->[$_->{status}] ]]</td> + <td class="tc3">[[= formatdate('%Y-%m-%d', $_->{date}, 'dh') ]]</td> + [[ if($d{user}{username} eq $p{AuthUsername}) { ]] + <td class="tc4">[[: $_->{comments}||'-' ]]</td> + <td class="tc5"><input type="checkbox" name="sel" value="[[= $_->{vid} ]]" /></td>[[ } ]] + </tr> + [[ } ]]- +</table> +[[ if($d{user}{username} eq $p{AuthUsername}) { ]] +<select id="vnlistchange" name="vnlistchange" class="right"> + <option value="-3">- with selected -</option> + <option value="-1">Delete</option> + <option value="-2">Update personal note</option> + <optgroup label="Update status:"> + [[ for (0..$#$VNDB::LSTAT) { ]]- + <option value="[[= $_ ]]">[[: $VNDB::LSTAT->[$_] ]]</option> + [[ } ]] + </optgroup> +</select> +</form>[[ } ]] +-[[= pagebut($purl) ]] +[[ } ]]- + +[[ if($d{user}{username} eq $p{AuthUsername}) { ]]- +<p> + <br /><br /> + NOTE: Your personal notes are only visible to you, other people can't see them. +</p>[[ } ]] diff --git a/data/tpl/vnpage b/data/tpl/vnpage new file mode 100644 index 00000000..15cb3235 --- /dev/null +++ b/data/tpl/vnpage @@ -0,0 +1,171 @@ +[[= ttabs('v', $d{vn}) ]] +<h2>[[: $d{vn}{title} ]]</h2> + +[[ if($d{vn}{hidden}) { ]]- + <span class="warning"> + This item has been deleted from the database. File a request on the + <a href="http://forum.vndb.org/index.php?board=5.0">forums</a> + to undelete this page. + </span> +[[ } ]] +[[ if(!$d{vn}{hidden} || $p{Authdel}) { ]]- + + +[[ if($d{change}) { ]] +[[= cdiff($d{prev}, $d{vn}, + [ title => 'Title', 1 ], + [ alias => 'Alias', 1 ], + [ desc => 'Description', 1, 1 ], + [ length => 'Length', sub { $VNDB::VNLEN->[$_[0] ][0] } ], + [ l_wp => 'Wikipedia link', sub { $_[0] ? '<a href="http://en.wikipedia.org/wiki/'.$_[0].'">'.$_[0].'</a>' : 'No link' } ], + [ l_vnn => 'V-N.net link', sub { $_[0] ? '<a href="http://visual-novels.net/vn/index.php?option=com_content&task=view&id='.$_[0].'">'.$_[0].'</a>' : 'No link' } ], + [ l_cisv => 'CISVisual link', sub { $_[0] ? '<a href="http://cisvisual.net/title/'.$_[0].'">'.$_[0].'</a>' : 'No link' } ], + [ categories => 'Categories', sub { join(' ', map { $VNDB::CAT->{substr($_->[0],0,1)}[1]{substr($_->[0],1,2)}.'('.$_->[1].')' } sort { $a->[0] cmp $b->[0] } @{$_[0]}) || 'No categories selected' }, 1 ], + [ relations => 'Relations', sub { join("<br />\n", map { $VNDB::VREL->[$_->{relation}].': '._hchar($_->{title}) } sort { $a->{id} <=> $b->{id} } @{$_[0]}) } ], + [ image => 'Image', sub { $_[0] ? sprintf '<img src="%s/cv/%02d/%d.jpg" />', $p{st}, $_[0]%50, $_[0] : 'No image'; } ], + [ img_nsfw => 'NSFW', sub { $_[0] ? 'Not safe' : 'Safe' } ] + ) ]] +[[ } ]]- + +[[ + my @lang; + for (@{$d{rel}}) { + my $l = $_->{language}; + next if grep { $_ eq $l } @lang; + push @lang, $l; + } + +]] + + +<div id="vnheader"> +<div> +[[ if($d{vn}{image}) { ]] + [[ if($d{vn}{img_nsfw} && !$p{AuthNsfw}) { ]] + <img src="[[: $p{st} ]]/cv/nsfw.png" id="nsfw" class="[[: $p{st} ]]/cv/[[= sprintf '%02d/%d', $d{vn}{image}%50, $d{vn}{image} ]].jpg" /> + [[ } else { ]] + <img src="[[: $p{st} ]]/cv/[[= sprintf '%02d/%d', $d{vn}{image}%50, $d{vn}{image} ]].jpg" alt="[[: $p{PageTitle} ]]" /> + [[ } ]] +[[ } else { ]]- + No image uploaded yet... +[[ } ]]- +</div> + + +-[[ if($p{AuthLoggedin}) { ]] +<p class="mod">< user options - + <a href="/u[[= $p{AuthId} ]]/votes" rel="voteDD" class="dropdown">[[= $d{vote}{vid} ? 'your vote: '.$d{vote}{vote} : 'vote' ]]</a> +- <a href="/u[[= $p{AuthId} ]]/list" rel="listDD" class="dropdown">[[= !$d{list}{vid} ? 'add to vn list' : 'status: '.lc $VNDB::LSTAT->[$d{list}{status}] ]]</a> +></p> +[[ } ]]- + +-[[ + $d{vn}{c_votes} =~ s#^([0-9]{2}.[0-9]{2})\|([0-9]{4})$#$2 == 0 ? 'No votes yet' : + $1 == 0 ? sprintf 'N/A (%d vote%s)', $2, $2>1?'s':'' : sprintf '%.2f (%d vote%s)', $1, $2, $2>1?'s':''#e; + + my @links = ( + $d{vn}{l_wp} ? [ 'Wikipedia', 'http://en.wikipedia.org/wiki/%s', $d{vn}{l_wp} ] : (), + $d{vn}{l_vnn} ? [ 'V-N.net', 'http://visual-novels.net/vn/index.php?option=com_content&task=view&id=%d', $d{vn}{l_vnn} ] : (), + $d{vn}{l_cisv} ? [ 'CISVisual', 'http://cisvisual.net/title/%d', $d{vn}{l_cisv} ] : (), + ); + +if($d{vn}{length} || $d{vn}{alias} || @links) { ]] + <h3>General info</h3> + <dl> + [[ if($d{vn}{length}) { ]]- + <dt>Length</dt><dd>[[: $VNDB::VNLEN->[$d{vn}{length}][0] ]]- ([[: $VNDB::VNLEN->[$d{vn}{length}][1] ]])</dd>[[ } ]]- + [[ if($d{vn}{alias}) { ]]- + <dt>Aliases</dt><dd>[[: $d{vn}{alias} ]]</dd>[[ } ]]- + [[ if(@links > 0) { ]] + <dt>Links</dt><dd>[[= join(', ', map { '<a href="'.sprintf($_->[1],$_->[2]).'">'.$_->[0].'</a>' } @links) ]]</dd>[[ } ]]- + </dl> +[[ } ]]- + + [[ if(@{$d{vn}{categories}}) { my %nolvl = (pli=>1,pbr=>1,gaa=>1,gab=>1); ]]- + <h3>Categories</h3> + <dl class="vncat"> + [[ for (sort keys %$VNDB::CAT) { + my $c = $_; + my @c = map { my $s=$_; + my ($cs) = grep { $_->[0] eq $c.$s } @{$d{vn}{categories}}; + $cs ? sprintf('<i class="crgn%d">%s</i>', $nolvl{$c.$_}?0:$cs->[1], $VNDB::CAT->{$c}[1]{$s}) + : () + } sort keys %{$VNDB::CAT->{$c}[1]}; + if(@c) { ]]- + <dt>[[: $VNDB::CAT->{$c}[0] ]]</dt><dd>[[= join(', ', @c) ]]</dd> + [[ } } ]] + </dl> + [[ } ]]- + + [[ if($#{$d{vn}{relations}} >= 0) { ]]- + <h3>[[= $d{page} eq 'rg' ? 'Relations' : '<a href="/v'.$d{vn}{id}.'/rg">Relations</a>' ]]</h3> + <dl class="vnrel"> + [[ my $lrel = -1; my $i=0; for (sort { $a->{relation} <=> $b->{relation} } @{$d{vn}{relations}}) { + if($_->{relation} != $lrel) { $lrel=$_->{relation}; if($i) { ]]</dd>[[ } ]]- + <dt>[[: $VNDB::VREL->[$lrel] ]]</dt><dd><a href="/v[[= $_->{id} ]]">[[: $_->{title} ]]</a> + [[ } else { ]]<br /><a href="/v[[= $_->{id} ]]" title="[[: $_->{title} ]]">[[: shorten $_->{title}, 40 ]]</a>[[ } + ++$i;} ]] + </dl> + [[ } ]]- + + [[ if(@lang && grep { @{$_->{producers}} } @{$d{rel}}) { ]]- + <h3>Producers</h3> + <dl> + [[ for my $l (@lang) { my %l; + $_->{language} eq $l && (%l = ( %l, map { + sprintf('<a href="/p%d" title="%s">%s</a>', + $_->{id}, _hchar($_->{name}), _hchar shorten $_->{name}, 30) => 1 + } @{$_->{producers}} )) for (@{$d{rel}}); + if(keys %l) { ]]- + <dt>[[: $VNDB::LANG->{$l} ]]</dt><dd>[[= join(' & ', keys %l) ]]</dd> + [[ } } ]] + </dl> + [[ } ]]- + + <h3>[[= $d{page} eq 'stats' ? 'User stats' : '<a href="/v'.$d{vn}{id}.'/stats">User stats</a>' ]]</h3> + <dl> + <dt>Rating</dt><dd>[[: $d{vn}{c_votes} ]]</dd> + </dl> +</div> + +-[[ + my @lnks = ( + !$d{page} ? '<b>description & releases</b>' : '<a href="/v'.$d{vn}{id}.'">description & releases</a>', + $d{page} eq 'stats' ? '<b>stats</b>' : '<a href="/v'.$d{vn}{id}.'/stats">stats</a>', + $d{vn}{rgraph} ? ( + $d{page} eq 'rg' ? '<b>relations</b>' : '<a href="/v'.$d{vn}{id}.'/rg">relations</a>', + ) : (), + ); +]] +<p class="opts">- -[[= join(' - ', @lnks) ]]- -</p> + +[[ if(!$d{page}) { ]][[+ vnpage_rel ]][[ } ]] +[[ if($d{page} eq 'stats') { ]][[+ vnpage_stats ]][[ } ]] +[[ if($d{page} eq 'rg') { ]][[+ vnpage_rg ]][[ } ]] + +[[ if($p{AuthLoggedin}) { ]]- + +<div class="dropdown" id="voteDD"> + <ul> + [[ if($d{vote}{vid}) { ]]- + <li><a href="/v[[= $d{vn}{id} ]]/vote?v=-1">revoke</a></li> + [[ } for (reverse 1..10) { ]]- + <li class="center"><a href="/v[[= $d{vn}{id} ]]/vote?v=[[= $_ ]]">[[= $_ ]]</a></li> + [[ } ]] + </ul> +</div> + +<div class="dropdown" id="listDD"> + <ul> + [[ for (0..$#$VNDB::LSTAT) { ]]- + <li><a href="/v[[= $d{vn}{id} ]]/list?s=[[= $_ ]]" [[= $_ == 6 ? ' id="askcomment"' : '' ]]>[[: $VNDB::LSTAT->[$_] ]]</a></li> + [[ } if($d{list}{vid}) { ]]- + <li><a href="/v[[= $d{vn}{id} ]]/list?s=-1">Remove</a></li> + [[ } ]]- + </ul> +</div> + +[[ } ]] + + +[[ } ]] diff --git a/data/tpl/vnpage_rel b/data/tpl/vnpage_rel new file mode 100644 index 00000000..f2570548 --- /dev/null +++ b/data/tpl/vnpage_rel @@ -0,0 +1,51 @@ +<h3>Description</h3> +<p class="desc"> + [[= summary($d{vn}{desc}) ]] + <br /><br /><br /> +</p> + + + +[[ + my @lang; + for (@{$d{rel}}) { + my $l = $_->{language}; + next if grep { $_ eq $l } @lang; + push @lang, $l; + } + +]] + + +<h3>Releases +[[ if((!$d{vn}{locked} && $p{Authedit}) || $p{Authlock}) { ]]- <p class="actions">(<a href="/v[[= $d{vn}{id} ]]/add">add release</a>)</p>[[ } ]]</h3> +[[ if(@{$d{rel}}) { ]]- +<table id="tre"> +[[ for(@lang) { my $l = $_; ]]- +<tr class="lang"> + <td colspan="6">[[: $VNDB::LANG->{$l} ]]</td> +</tr> +[[ for (@{$d{rel}}) { next if $l ne $_->{language}; ]]- + <tr> + <td class="tc1">[[= datestr($_->{released}) ]]</td> + <td class="tc2">[[= $_->{minage}<0 ? '' : $VNDB::VRAGES->{$_->{minage}} ]]</td> + <td class="tc3">[[= join('', map { $_ ne 'oth' ? '<acronym class="plat '.$_.'" title="'._hchar($VNDB::PLAT->{$_}).'">'.$_.'</acronym>' : () } sort @{$_->{platforms}}) ]]</td> + <td class="tc4"><acronym title="[[= $VNDB::RTYP->[$_->{type}] ]]- release">[[= lc substr($VNDB::RTYP->[$_->{type}],0,1) ]]</acronym></td> + <td class="tc5"><a href="/r[[= $_->{id} ]]" title="[[: $_->{original} || $_->{title} ]]">[[: shorten $_->{title},60 ]]</a></td> +<!-- <td class="tc6">[[= + join(', ', + map { + sprintf('<a href="/p%d" title="%s">%s</a>', $_->{id}, _hchar($_->{name}), _hchar(shorten $_->{name},20)) } @{$_->{producers}}) ]]</td>--> + <td class="tc7">[[ if($_->{website}) { ]]<a href="[[: $_->{website} ]]"><acronym class="plat ext" title="WWW">www</acronym></a>[[ } ]]</td> + </tr> +[[ } ]]- +[[ } ]]- +</table> +[[ } else { ]]- +<p> + This game has either not been released yet, or we just don't have information about + any releases. +</p> +[[ } ]] + + diff --git a/data/tpl/vnpage_rg b/data/tpl/vnpage_rg new file mode 100644 index 00000000..d988e226 --- /dev/null +++ b/data/tpl/vnpage_rg @@ -0,0 +1,11 @@ +<h3>Relations</h3> +[[ if(!$d{vn}{rgraph}) { ]] + <p> + Relation graph has not been generated yet... + </p> +[[ } else { ]] + [[= $d{vn}{rmap} ]] + <p id="relations"> + <img src="[[= sprintf "%s/rg/%02d/%d.gif", $p{st}, $d{vn}{rgraph}%50, $d{vn}{rgraph} ]]" usemap="#rgraph" /> + </p> +[[ } ]] diff --git a/data/tpl/vnpage_stats b/data/tpl/vnpage_stats new file mode 100644 index 00000000..dde9aed3 --- /dev/null +++ b/data/tpl/vnpage_stats @@ -0,0 +1,68 @@ +<ul id="stats"> +[[ + my $max = 1; my $total = 0; my $sum = 0; + for (0..$#{$d{votes}{graph}}) { + $total += $d{votes}{graph}[$_]; + $max = $d{votes}{graph}[$_] if $d{votes}{graph}[$_] > $max; + $sum += ($_+1) * $d{votes}{graph}[$_]; + } +]] +[[ if(!$d{user} || ($d{pv} && $d{user}{votes})) { ]]- +<li><h3>Vote graph <b class="actions">[[= $total ]]- vote[[= $total==1?'':'s' ]]- total + [[= $total ? sprintf(', average: %.1f.', $sum/$total) : '' ]]</b></h3> +<table id="tvg"> +[[ for (0..$#{$d{votes}{graph}}) { ]]- + <tr> + <td class="tc1">[[= $_+1 ]]</td> + <td class="tc2"><div style="width: -[[= ($d{votes}{graph}[$_]/$max)*270 + 5 ]]px"> </div>[[= $d{votes}{graph}[$_] ]]</td> + </tr> +[[ } ]]- +</table></li> + +[[ if($#{$d{votes}{latest}} >= 0) { ]] +<li><h3>Recent votes</h3> +<table id="tvr"> +[[ for (@{$d{votes}{latest}}) { ]]- + <tr> + [[ if(!$d{user}) { ]]- + <td class="tc1"><a href="/u[[= $_->{uid} ]]">[[: $_->{username} ]]</a></td> + [[ } else { ]]- + <td class="tc1"><a href="/v[[= $_->{vid} ]]">[[: length($_->{title})>30?substr($_->{title},0,27).'...':$_->{title} ]]</a></td> + [[ } ]]- + <td class="tc2">[[= $_->{vote} ]]</td> + <td class="tc3">[[= formatdate('%Y-%m-%d %R', $_->{date}, 'dh') ]]</td> + </tr> +[[ } ]]- +</table></li> +[[ } } ]]- + +-[[ $max = 1; $total = 0; + for (@{$d{lists}{graph}}) { $total += $_; $max = $_ if $_ > $max; } ]] +[[ if(!$d{user} || ($d{pl} && $d{user}{vnlist})) { ]]- +<li class="break"><h3>VN List stats <b class="actions">[[= $total ]]- -[[= $d{user}?'visual novel':'user' ]][[= $total==1?'':'s' ]]- total</b></h3> +<table id="tus"> + [[ for (0..$#$VNDB::LSTAT) { ]]- + <tr> + <td class="tc1">[[= $VNDB::LSTAT->[$_] ]]</td> + <td class="tc2"><div style="width: -[[= ($d{lists}{graph}[$_]/$max)*235 + 5 ]]px"> </div>[[= $d{lists}{graph}[$_] ]]</td> + </tr> + [[ } ]]- +</table></li> + +[[ if($#{$d{lists}{latest}} >= 0) { ]] +<li><h3>Recent VN list additions</h3> +<table id="tur"> +[[ for (@{$d{lists}{latest}}) { ]]- + <tr> + [[ if(!$d{user}) { ]]- + <td class="tc1"><a href="/u[[= $_->{uid} ]]">[[: $_->{username} ]]</a></td> + [[ } else { ]]- + <td class="tc1"><a href="/v[[= $_->{vid} ]]">[[: length($_->{title})>25?substr($_->{title},0,23).'...':$_->{title} ]]</a></td> + [[ } ]]- + <td class="tc2">[[= $VNDB::LSTAT->[$_->{status}] ]]</td> + <td class="tc3">[[= formatdate('%Y-%m-%d %R', $_->{date}, 'dh') ]]</td> + </tr> +[[ } ]]- +</table></li> +[[ } } ]]- +</ul> |