From 3a6a1dabe45d5fcdfd882de65c24ac45f173803e Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 8 Apr 2011 16:58:58 +0200 Subject: Bugfix: Forgot to make two JS strings translatable --- ChangeLog | 1 + data/lang.txt | 14 ++++++++++++++ data/script.js | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9186e339..91bb01f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ - Bugfix: Hide pointless groups and commas on spoiler-hidden trait display - Bugfix: Properly format future dates on my vn list - Bugfix: Properly position the sub-tabs on VN page without tags + - Bugfix: Forgot to make two JS strings translatable 2.19 - 2011-03-30 - Character database: diff --git a/data/lang.txt b/data/lang.txt index f037b61e..f69e20b9 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -5431,6 +5431,13 @@ cs : Přidat vlastnost hu : Sajátosság hozzáadása nl : Voeg kenmerk toe +:_chare_traits_del +en : del +ru*: +cs*: +hu*: +nl : + :_chare_traits_present en : Selected trait is already present. ru*: @@ -5515,6 +5522,13 @@ cs : VN je již přítomna. hu : A VN már jelen van. nl : VN is al geselecteerd. +:_chare_vns_relexists +en : Release already present. +ru*: +cs*: +hu*: +nl : Uitgave is al geselecteerd. + # Character browser (/c/*) diff --git a/data/script.js b/data/script.js index 97f5fa30..4fc3e49b 100644 --- a/data/script.js +++ b/data/script.js @@ -1814,7 +1814,7 @@ function ctrAdd(item, spoil) { tag('b', {'class':'grayedout'}, group?group+' / ':''), tag('a', {'href':'/i'+id}, name)), sp, - tag('td', {'class':'tc_del'}, tag('a', {href:'#', onclick:ctrDel}, 'del')) + tag('td', {'class':'tc_del'}, tag('a', {href:'#', onclick:ctrDel}, mt('_chare_traits_del'))) )); ctrEmpty(); ctrSerialize(); @@ -1994,7 +1994,7 @@ function cvnRelChange() { while(tr.nodeName.toLowerCase() != 'tr') tr = tr.parentNode; if(byId('cvn_v'+tr.cvn_vid+'r'+val)) { - alert('Release already selected.'); + alert(mt('_chare_vns_relexists')); for(var i=0; i Date: Fri, 8 Apr 2011 17:09:48 +0200 Subject: Added spoiler warning to character revision pages --- ChangeLog | 1 + data/lang.txt | 14 ++++++++++++++ data/style.css | 4 ++-- lib/VNDB/Util/CommonHTML.pm | 11 ++++++++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91bb01f7..b9319ac9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ - Order the VNs listed on char browser by release date - Order the traits groups on /i by their 'order' column - Use same browsing-table on trait pages and char browser + - Added spoiler warning to character revision pages - CSS: Hide links in [spoiler] tags - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser diff --git a/data/lang.txt b/data/lang.txt index f69e20b9..ed0033e7 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -2143,6 +2143,20 @@ nl : laatste # Revision pages +:_revision_spoil_title +en : SPOILER WARNING! +ru*: +cs*: +hu*: +nl : SPOILERWAARSCHUWING! + +:_revision_spoil_msg +en : This revision page may contain major spoilers. You may want to view the [url,_1,final page] instead. +ru*: +cs*: +hu*: +nl : Deze revisiepagina kan spoilers bevatten. Je kan misschien beter de [url,_1,uiteindelijke pagina] openen. + :_revision_previous en : earlier revision ru : более ранняя редакция diff --git a/data/style.css b/data/style.css index 5b35e7af..cb936dbc 100644 --- a/data/style.css +++ b/data/style.css @@ -1068,7 +1068,7 @@ div.warning li, div.notice li { div.revision { padding-bottom: 10px!important; } -div.revision div, div.revision table { +div.revision div.rev, div.revision table { border: 1px solid $border$; margin: 0 auto; width: 90%; @@ -1087,7 +1087,7 @@ div.revision table td { div.revision td.tcval { width: 44%; } -div.revision div { +div.revision div.rev { padding: 5px; text-align: center; } diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index 41370b4b..e1765d0d 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -163,6 +163,15 @@ sub htmlRevision { div class => 'mainbox revision'; h1 mt '_revision_title', $new->{rev}; + # character information may be rather spoilerous + if($type eq 'c') { + div class => 'warning'; + h2 mt '_revision_spoil_title'; + lit mt '_revision_spoil_msg', "/c$new->{id}"; + end; + br;br; + } + # previous/next revision links a class => 'prev', href => sprintf('/%s%d.%d', $type, $new->{id}, $new->{rev}-1), '<- '.mt '_revision_previous' if $new->{rev} > 1; @@ -174,7 +183,7 @@ sub htmlRevision { # no previous revision, just show info about the revision itself if(!$old) { - div; + div class => 'rev'; revheader($self, $type, $new); br; b mt '_revision_new_summary'; -- cgit v1.2.3 From 9c0a0b51a115ab95fc4d78bf52d5785d6088ee85 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 8 Apr 2011 18:34:07 +0200 Subject: Generate dbedit/dbdel notifications on character edits --- ChangeLog | 1 + Makefile | 8 +++++++- util/sql/all.sql | 4 +++- util/sql/func.sql | 38 ++++++++++++++++++++++---------------- util/updates/update_2.20.sql | 11 +++++++++++ 5 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 util/updates/update_2.20.sql diff --git a/ChangeLog b/ChangeLog index b9319ac9..20e11ace 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ - Order the traits groups on /i by their 'order' column - Use same browsing-table on trait pages and char browser - Added spoiler warning to character revision pages + - Generate dbedit/dbdel notifications on character edits - CSS: Hide links in [spoiler] tags - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser diff --git a/Makefile b/Makefile index d1ed33fe..568eb1b0 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ .PHONY: all dirs js skins robots chmod chmod-tladmin multi-stop multi-start multi-restart sql-import\ update-2.10 update-2.11 update-2.12 update-2.13 update-2.14 update-2.15 update-2.16 update-2.17\ - update-2.18 update-2.19 + update-2.18 update-2.19 update-2.20 all: dirs js skins robots data/config.pl @@ -179,3 +179,9 @@ update-2.19: all $(multi-stop) ${runpsql} < util/updates/update_2.19.sql $(multi-start) + +update-2.20: all + $(multi-stop) + ${runpsql} < util/updates/update_2.20.sql + $(multi-start) + diff --git a/util/sql/all.sql b/util/sql/all.sql index d05297da..a98fbf95 100644 --- a/util/sql/all.sql +++ b/util/sql/all.sql @@ -12,7 +12,7 @@ CREATE TYPE gender AS ENUM ('unknown', 'm', 'f', 'b'); CREATE TYPE language AS ENUM ('cs', 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja', 'ko', 'nl', 'no', 'pl', 'pt-pt', 'pt-br', 'ru', 'sk', 'sv', 'tr', 'vi', 'zh'); CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); CREATE TYPE notification_ntype AS ENUM ('pm', 'dbdel', 'listdel', 'dbedit', 'announce'); -CREATE TYPE notification_ltype AS ENUM ('v', 'r', 'p', 't'); +CREATE TYPE notification_ltype AS ENUM ('v', 'r', 'p', 'c', 't'); CREATE TYPE prefs_key AS ENUM ('l10n', 'skin', 'customcss', 'filter_vn', 'filter_release', 'show_nsfw', 'hide_list', 'notify_nodbedit', 'notify_announce'); CREATE TYPE producer_relation AS ENUM ('old', 'new', 'sub', 'par', 'imp', 'ipa', 'spa', 'ori'); CREATE TYPE release_type AS ENUM ('complete', 'partial', 'trial'); @@ -88,11 +88,13 @@ CREATE TRIGGER notify_pm AFTER INSERT ON threads_pos CREATE TRIGGER notify_dbdel AFTER UPDATE ON vn FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_dbdel(); CREATE TRIGGER notify_dbdel AFTER UPDATE ON producers FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_dbdel(); CREATE TRIGGER notify_dbdel AFTER UPDATE ON releases FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_dbdel(); +CREATE TRIGGER notify_dbdel AFTER UPDATE ON chars FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_dbdel(); CREATE TRIGGER notify_listdel AFTER UPDATE ON vn FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_listdel(); CREATE TRIGGER notify_listdel AFTER UPDATE ON releases FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_listdel(); CREATE TRIGGER notify_dbedit AFTER UPDATE ON vn FOR EACH ROW WHEN (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) EXECUTE PROCEDURE notify_dbedit(); CREATE TRIGGER notify_dbedit AFTER UPDATE ON producers FOR EACH ROW WHEN (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) EXECUTE PROCEDURE notify_dbedit(); CREATE TRIGGER notify_dbedit AFTER UPDATE ON releases FOR EACH ROW WHEN (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) EXECUTE PROCEDURE notify_dbedit(); +CREATE TRIGGER notify_dbedit AFTER UPDATE ON chars FOR EACH ROW WHEN (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) EXECUTE PROCEDURE notify_dbedit(); CREATE TRIGGER notify_announce AFTER INSERT ON threads_posts FOR EACH ROW WHEN (NEW.num = 1) EXECUTE PROCEDURE notify_announce(); CREATE TRIGGER vn_vnsearch_notify AFTER UPDATE ON vn FOR EACH ROW diff --git a/util/sql/func.sql b/util/sql/func.sql index 75e5ecad..b0dbfff2 100644 --- a/util/sql/func.sql +++ b/util/sql/func.sql @@ -802,16 +802,16 @@ END; $$ LANGUAGE plpgsql; --- called on UPDATE vn / producers / releases when (NOT OLD.hidden AND NEW.hidden) +-- called on UPDATE vn / producers / releases / chars when (NOT OLD.hidden AND NEW.hidden) CREATE OR REPLACE FUNCTION notify_dbdel() RETURNS trigger AS $$ BEGIN INSERT INTO notifications (ntype, ltype, uid, iid, subid, c_title, c_byuser) SELECT DISTINCT 'dbdel'::notification_ntype, - (CASE TG_TABLE_NAME WHEN 'vn' THEN 'v' WHEN 'releases' THEN 'r' ELSE 'p' END)::notification_ltype, - c.requester, NEW.id, c2.rev, x.title, c2.requester + (CASE TG_TABLE_NAME WHEN 'vn' THEN 'v' WHEN 'releases' THEN 'r' WHEN 'producers' THEN 'p' ELSE 'c' END)::notification_ltype, + h.requester, NEW.id, h2.rev, x.title, h2.requester -- look for changes of the deleted entry -- this method may look a bit unintuitive, but it's way faster than doing LEFT JOINs - FROM changes c + FROM changes h JOIN ( SELECT vr.id, vr2.title FROM vn_rev vr JOIN vn v ON v.id = vr.vid JOIN vn_rev vr2 ON vr2.id = v.latest WHERE TG_TABLE_NAME = 'vn' AND vr.vid = NEW.id @@ -821,12 +821,15 @@ BEGIN UNION SELECT pr.id, pr2.name FROM producers_rev pr JOIN producers p ON p.id = pr.pid JOIN producers_rev pr2 ON pr2.id = p.latest WHERE TG_TABLE_NAME = 'producers' AND pr.pid = NEW.id - ) x(id, title) ON c.id = x.id + UNION SELECT cr.id, cr2.name FROM chars_rev cr + JOIN chars c ON c.id = cr.cid JOIN chars_rev cr2 ON cr2.id = c.latest + WHERE TG_TABLE_NAME = 'chars' AND cr.cid = NEW.id + ) x(id, title) ON h.id = x.id -- join info about the deletion itself - JOIN changes c2 ON c2.id = NEW.latest - WHERE c.requester <> 1 -- exclude Multi + JOIN changes h2 ON h2.id = NEW.latest + WHERE h.requester <> 1 -- exclude Multi -- exclude the user who deleted the entry - AND c.requester <> c2.requester; + AND h.requester <> h2.requester; RETURN NULL; END; $$ LANGUAGE plpgsql; @@ -862,16 +865,16 @@ END; $$ LANGUAGE plpgsql; --- called on UPDATE vn / producers / releases when (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) +-- called on UPDATE vn / producers / releases / chars when (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) -- this trigger is very similar to notify_dbdel() CREATE OR REPLACE FUNCTION notify_dbedit() RETURNS trigger AS $$ BEGIN INSERT INTO notifications (ntype, ltype, uid, iid, subid, c_title, c_byuser) SELECT DISTINCT 'dbedit'::notification_ntype, - (CASE TG_TABLE_NAME WHEN 'vn' THEN 'v' WHEN 'releases' THEN 'r' ELSE 'p' END)::notification_ltype, - c.requester, NEW.id, c2.rev, x.title, c2.requester + (CASE TG_TABLE_NAME WHEN 'vn' THEN 'v' WHEN 'releases' THEN 'r' WHEN 'producers' THEN 'p' ELSE 'c' END)::notification_ltype, + h.requester, NEW.id, h2.rev, x.title, h2.requester -- look for changes of the edited entry - FROM changes c + FROM changes h JOIN ( SELECT vr.id, vr2.title FROM vn_rev vr JOIN vn v ON v.id = vr.vid JOIN vn_rev vr2 ON vr2.id = v.latest WHERE TG_TABLE_NAME = 'vn' AND vr.vid = NEW.id @@ -881,13 +884,16 @@ BEGIN UNION SELECT pr.id, pr2.name FROM producers_rev pr JOIN producers p ON p.id = pr.pid JOIN producers_rev pr2 ON pr2.id = p.latest WHERE TG_TABLE_NAME = 'producers' AND pr.pid = NEW.id - ) x(id, title) ON c.id = x.id + UNION SELECT cr.id, cr2.name FROM chars_rev cr + JOIN chars c ON c.id = cr.cid JOIN chars_rev cr2 ON cr2.id = c.latest + WHERE TG_TABLE_NAME = 'chars' AND cr.cid = NEW.id + ) x(id, title) ON h.id = x.id -- join info about the deletion itself - JOIN changes c2 ON c2.id = NEW.latest + JOIN changes h2 ON h2.id = NEW.latest -- exclude the user who edited the entry - WHERE c.requester <> c2.requester + WHERE h.requester <> h2.requester -- exclude users who don't want this notify - AND NOT EXISTS(SELECT 1 FROM users_prefs up WHERE uid = c.requester AND key = 'notify_nodbedit'); + AND NOT EXISTS(SELECT 1 FROM users_prefs up WHERE uid = h.requester AND key = 'notify_nodbedit'); RETURN NULL; END; $$ LANGUAGE plpgsql; diff --git a/util/updates/update_2.20.sql b/util/updates/update_2.20.sql new file mode 100644 index 00000000..236161d2 --- /dev/null +++ b/util/updates/update_2.20.sql @@ -0,0 +1,11 @@ + +ALTER TYPE notification_ltype RENAME TO tmp; +CREATE TYPE notification_ltype AS ENUM ('v', 'r', 'p', 'c', 't'); +ALTER TABLE notifications ALTER COLUMN ltype TYPE notification_ltype USING ltype::text::notification_ltype; +DROP TYPE tmp; + +\i util/sql/func.sql + +CREATE TRIGGER notify_dbdel AFTER UPDATE ON chars FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_dbdel(); +CREATE TRIGGER notify_dbedit AFTER UPDATE ON chars FOR EACH ROW WHEN (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) EXECUTE PROCEDURE notify_dbedit(); + -- cgit v1.2.3 From c0b8fb4a60dda06bbe306273de8ac0cd92156fd6 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 8 Apr 2011 18:41:54 +0200 Subject: Added 'select' all to wishlist and moved 'select all' down on notifies For consistency --- ChangeLog | 1 + lib/VNDB/Handler/ULists.pm | 3 +++ lib/VNDB/Handler/Users.pm | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 20e11ace..b67a5917 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ - Added spoiler warning to character revision pages - Generate dbedit/dbdel notifications on character edits - CSS: Hide links in [spoiler] tags + - Added 'select' all to wishlist and moved 'select all' down on notifies - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser - Bugfix: properly announce chars and traits in Multi::IRC diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm index 363c2262..1c82d982 100644 --- a/lib/VNDB/Handler/ULists.pm +++ b/lib/VNDB/Handler/ULists.pm @@ -239,6 +239,7 @@ sub wishlist { { post => 'sel', required => 0, default => 0, multi => 1, template => 'int' }, { post => 'batchedit', required => 1, enum => [ -1, @{$self->{wishlist_status}} ] }, ); + $frm->{sel} = [ grep $_, @{$frm->{sel}} ]; # weed out "select all" checkbox if(!$frm->{_err} && @{$frm->{sel}} && $frm->{sel}[0]) { $self->dbWishListDel($uid, $frm->{sel}) if $frm->{batchedit} == -1; $self->dbWishListAdd($frm->{sel}, $uid, $frm->{batchedit}) if $frm->{batchedit} >= 0; @@ -303,6 +304,8 @@ sub wishlist { $own ? (footer => sub { Tr; td colspan => 3; + input type => 'checkbox', class => 'checkall', name => 'sel', value => 0; + txt ' '; Select name => 'batchedit', id => 'batchedit'; option mt '_wishlist_select'; optgroup label => mt '_wishlist_changeprio'; diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index 75ddb547..6cedc734 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -611,7 +611,7 @@ sub notifies { class => 'notifies', pageurl => "/u$uid/notifies?r=$f->{r}", header => [ - [ '' ], + [ '' ], [ mt '_usern_col_type' ], [ mt '_usern_col_age' ], [ mt '_usern_col_id' ], @@ -639,6 +639,8 @@ sub notifies { footer => sub { Tr; td colspan => 5; + input type => 'checkbox', class => 'checkall', name => 'notifysel', value => 0; + txt ' '; input type => 'submit', name => 'markread', value => mt '_usern_but_markread'; input type => 'submit', name => 'remove', value => mt '_usern_but_remove'; b class => 'grayedout', ' '.mt '_usern_autodel'; -- cgit v1.2.3 From 50da6516a687442f09a05416ca1daff04d7bbf37 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 8 Apr 2011 19:08:45 +0200 Subject: Added char/tag/trait stats to database statistics box --- ChangeLog | 1 + data/lang.txt | 21 +++++++++++++++++++++ data/style.css | 2 +- lib/Multi/Maintenance.pm | 3 +++ lib/VNDB/Util/LayoutHTML.pm | 2 +- util/sql/all.sql | 9 +++++++++ util/sql/func.sql | 16 +++++++++++++--- util/updates/update_2.20.sql | 13 +++++++++++++ 8 files changed, 62 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b67a5917..59185a2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ - Generate dbedit/dbdel notifications on character edits - CSS: Hide links in [spoiler] tags - Added 'select' all to wishlist and moved 'select all' down on notifies + - Added char/tag/trait stats to database statistics box - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser - Bugfix: properly announce chars and traits in Multi::IRC diff --git a/data/lang.txt b/data/lang.txt index ed0033e7..bee15a28 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -1985,6 +1985,27 @@ cs : Producenti hu : Készítők nl : Producenten +:_menu_stat_chars +en : Characters +ru*: +cs*: +hu*: +nl : Karakters + +:_menu_stat_tags +en : VN Tags +ru*: +cs*: +hu*: +nl : + +:_menu_stat_traits +en : Character traits +ru*: +cs*: +hu*: +nl : Karakter kenmerken + :_menu_stat_users en : Users ru : Пользователей diff --git a/data/style.css b/data/style.css index cb936dbc..1381114c 100644 --- a/data/style.css +++ b/data/style.css @@ -289,7 +289,7 @@ b.future, b.standout, a.standout { #menulist dt { display: block; float: left; - width: 85px; + width: 93px; font-style: italic; } #menulist dd { diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index 5b092d0a..44cb6552 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -216,6 +216,9 @@ sub statscache { q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM vn WHERE hidden = FALSE) WHERE section = 'vn'|, q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM releases WHERE hidden = FALSE) WHERE section = 'releases'|, q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM producers WHERE hidden = FALSE) WHERE section = 'producers'|, + q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM chars WHERE hidden = FALSE) WHERE section = 'chars'|, + q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM tags WHERE state = 2) WHERE section = 'tags'|, + q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM traits WHERE state = 2) WHERE section = 'traits'|, q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM threads WHERE hidden = FALSE) WHERE section = 'threads'|, q|UPDATE stats_cache SET count = (SELECT COUNT(*) FROM threads_posts WHERE hidden = FALSE AND EXISTS(SELECT 1 FROM threads WHERE threads.id = tid AND threads.hidden = FALSE)) WHERE section = 'threads_posts'| diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index 22052a75..5dd8038f 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -130,7 +130,7 @@ sub _menu { h2 mt '_menu_dbstats'; div; dl; - for (qw|vn releases producers users threads posts|) { + for (qw|vn releases producers chars tags traits users threads posts|) { dt mt "_menu_stat_$_"; dd $self->{stats}{$_}; } diff --git a/util/sql/all.sql b/util/sql/all.sql index a98fbf95..eac8d58a 100644 --- a/util/sql/all.sql +++ b/util/sql/all.sql @@ -47,6 +47,12 @@ CREATE TRIGGER stats_cache_new AFTER INSERT ON producers CREATE TRIGGER stats_cache_edit AFTER UPDATE ON producers FOR EACH ROW WHEN (OLD.hidden IS DISTINCT FROM NEW.hidden) EXECUTE PROCEDURE update_stats_cache(); CREATE TRIGGER stats_cache_new AFTER INSERT ON releases FOR EACH ROW WHEN (NEW.hidden = FALSE) EXECUTE PROCEDURE update_stats_cache(); CREATE TRIGGER stats_cache_edit AFTER UPDATE ON releases FOR EACH ROW WHEN (OLD.hidden IS DISTINCT FROM NEW.hidden) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_new AFTER INSERT ON chars FOR EACH ROW WHEN (NEW.hidden = FALSE) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_edit AFTER UPDATE ON chars FOR EACH ROW WHEN (OLD.hidden IS DISTINCT FROM NEW.hidden) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_new AFTER INSERT ON tags FOR EACH ROW WHEN (NEW.state = 2) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_edit AFTER UPDATE ON tags FOR EACH ROW WHEN (OLD.state IS DISTINCT FROM NEW.state) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_new AFTER INSERT ON traits FOR EACH ROW WHEN (NEW.state = 2) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_edit AFTER UPDATE ON traits FOR EACH ROW WHEN (OLD.state IS DISTINCT FROM NEW.state) EXECUTE PROCEDURE update_stats_cache(); CREATE TRIGGER stats_cache_new AFTER INSERT ON threads FOR EACH ROW WHEN (NEW.hidden = FALSE) EXECUTE PROCEDURE update_stats_cache(); CREATE TRIGGER stats_cache_edit AFTER UPDATE ON threads FOR EACH ROW WHEN (OLD.hidden IS DISTINCT FROM NEW.hidden) EXECUTE PROCEDURE update_stats_cache(); CREATE TRIGGER stats_cache_new AFTER INSERT ON threads_posts FOR EACH ROW WHEN (NEW.hidden = FALSE) EXECUTE PROCEDURE update_stats_cache(); @@ -126,6 +132,9 @@ INSERT INTO stats_cache (section, count) VALUES ('vn', 0), ('producers', 0), ('releases', 0), + ('chars', 0), + ('tags', 0), + ('traits', 0), ('threads', 0), ('threads_posts', 0); diff --git a/util/sql/func.sql b/util/sql/func.sql index b0dbfff2..47b4511d 100644 --- a/util/sql/func.sql +++ b/util/sql/func.sql @@ -490,6 +490,9 @@ $$ LANGUAGE 'plpgsql'; -- the stats_cache table CREATE OR REPLACE FUNCTION update_stats_cache() RETURNS TRIGGER AS $$ +DECLARE + unhidden boolean; + hidden boolean; BEGIN IF TG_OP = 'INSERT' THEN IF TG_TABLE_NAME = 'users' THEN @@ -504,13 +507,20 @@ BEGIN END IF; END IF; - ELSIF TG_OP = 'UPDATE' AND TG_TABLE_NAME <> 'users' THEN - IF OLD.hidden = TRUE THEN + ELSIF TG_OP = 'UPDATE' THEN + IF TG_TABLE_NAME IN('tags', 'traits') THEN + unhidden := OLD.state <> 2 AND NEW.state = 2; + hidden := OLD.state = 2 AND NEW.state <> 2; + ELSE + unhidden := OLD.hidden AND NOT NEW.hidden; + hidden := NOT unhidden; + END IF; + IF unhidden THEN IF TG_TABLE_NAME = 'threads' THEN UPDATE stats_cache SET count = count+NEW.count WHERE section = 'threads_posts'; END IF; UPDATE stats_cache SET count = count+1 WHERE section = TG_TABLE_NAME; - ELSIF OLD.hidden = FALSE THEN + ELSIF hidden THEN IF TG_TABLE_NAME = 'threads' THEN UPDATE stats_cache SET count = count-NEW.count WHERE section = 'threads_posts'; END IF; diff --git a/util/updates/update_2.20.sql b/util/updates/update_2.20.sql index 236161d2..28efd713 100644 --- a/util/updates/update_2.20.sql +++ b/util/updates/update_2.20.sql @@ -9,3 +9,16 @@ DROP TYPE tmp; CREATE TRIGGER notify_dbdel AFTER UPDATE ON chars FOR EACH ROW WHEN (NOT OLD.hidden AND NEW.hidden) EXECUTE PROCEDURE notify_dbdel(); CREATE TRIGGER notify_dbedit AFTER UPDATE ON chars FOR EACH ROW WHEN (OLD.latest IS DISTINCT FROM NEW.latest AND NOT NEW.hidden) EXECUTE PROCEDURE notify_dbedit(); + +INSERT INTO stats_cache VALUES + ('chars', (SELECT COUNT(*) FROM chars WHERE NOT hidden)), + ('tags', (SELECT COUNT(*) FROM tags WHERE state = 2)), + ('traits', (SELECT COUNT(*) FROM traits WHERE state = 2)); + +CREATE TRIGGER stats_cache_new AFTER INSERT ON chars FOR EACH ROW WHEN (NEW.hidden = FALSE) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_edit AFTER UPDATE ON chars FOR EACH ROW WHEN (OLD.hidden IS DISTINCT FROM NEW.hidden) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_new AFTER INSERT ON tags FOR EACH ROW WHEN (NEW.state = 2) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_edit AFTER UPDATE ON tags FOR EACH ROW WHEN (OLD.state IS DISTINCT FROM NEW.state) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_new AFTER INSERT ON traits FOR EACH ROW WHEN (NEW.state = 2) EXECUTE PROCEDURE update_stats_cache(); +CREATE TRIGGER stats_cache_edit AFTER UPDATE ON traits FOR EACH ROW WHEN (OLD.state IS DISTINCT FROM NEW.state) EXECUTE PROCEDURE update_stats_cache(); + -- cgit v1.2.3 From 9304d1032723d3c2b9f3dad4d239f12c8c7268fa Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 8 Apr 2011 19:25:53 +0200 Subject: Update traits_chars cache daily using Multi::Maintenance I'd really prefer incremental updates, but I'll first need to find a proper algorithm... --- ChangeLog | 1 + data/lang.txt | 7 +++++++ lib/Multi/Maintenance.pm | 14 ++++++++++---- lib/VNDB/Handler/Chars.pm | 4 ---- lib/VNDB/Handler/Traits.pm | 6 +----- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 59185a2e..a8ce144a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ - CSS: Hide links in [spoiler] tags - Added 'select' all to wishlist and moved 'select all' down on notifies - Added char/tag/trait stats to database statistics box + - Update traits_chars cache daily using Multi::Maintenance - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser - Bugfix: properly announce chars and traits in Multi::IRC diff --git a/data/lang.txt b/data/lang.txt index bee15a28..b4951352 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -5696,6 +5696,13 @@ cs : Tato vlastnost ještě nebyla provázána s žádnými postavami nebo tyto hu : Ez a sajátosság még nincs hozzárendelve egy szereplőhöz se, vagy a spoiler beállításaid miatt, el vannak rejtve. nl : Dit kenmerk is nog niet gekoppeld aan een karakter, of deze worden niet weergegeven in verband met je spoilerinstelling. +:_traitp_cached +en : The list below also includes all characters linked to child traits. This list is cached, it can take up to 24 hours after a character has been edited for it to show up on this page. +ru*: +cs*: +hu*: +nl : De volgende lijst bevat ook alle karakters die gelinkt zijn aan subkenmerken. Deze lijst is gecached, het kan 24 uur duren voordat een karakter op deze pagina te zien is. + # Trait add/edit form (/i+/edit, /i+/add, /i/new) diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index 44cb6552..fb0c336f 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -18,13 +18,13 @@ sub spawn { package_states => [ $p => [qw| _start shutdown set_daily daily set_monthly monthly log_stats - vncache_inc tagcache vnpopularity vnrating cleangraphs cleansessions cleannotifications + vncache_inc tagcache traitcache vnpopularity vnrating cleangraphs cleansessions cleannotifications vncache_full usercache statscache logrotate vnsearch_check vnsearch_gettitles vnsearch_update |], ], heap => { - daily => [qw|vncache_inc tagcache vnpopularity vnrating cleangraphs cleansessions cleannotifications|], + daily => [qw|vncache_inc tagcache traitcache vnpopularity vnrating cleangraphs cleansessions cleannotifications|], monthly => [qw|vncache_full usercache statscache logrotate|], vnsearch_checkdelay => 3600, @_, @@ -121,13 +121,19 @@ sub vncache_inc { sub tagcache { - # takes about 2 seconds max, still OK + # takes about 5 seconds max, still OK $_[KERNEL]->post(pg => do => 'SELECT tag_vn_calc()', undef, 'log_stats', 'tagcache'); } +sub traitcache { + # still takes less than a second + $_[KERNEL]->post(pg => do => 'SELECT traits_chars_calc()', undef, 'log_stats', 'traitcache'); +} + + sub vnpopularity { - # still takes at most 3 seconds. let's hope that doesn't increase... + # takes a bit more than 8 seconds, meh... $_[KERNEL]->post(pg => do => 'SELECT update_vnpopularity()', undef, 'log_stats', 'vnpopularity'); } diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm index 7968b66c..dfa289be 100644 --- a/lib/VNDB/Handler/Chars.pm +++ b/lib/VNDB/Handler/Chars.pm @@ -331,10 +331,6 @@ sub edit { $frm->{vns} = \@vns; my $nrev = $self->dbItemEdit(c => !$copy && $id ? $r->{cid} : undef, %$frm); - - # TEMPORARY SOLUTION! I'll investigate more efficient solutions and incremental updates whenever I have more data - $self->dbExec('SELECT traits_chars_calc()'); - return $self->resRedirect("/c$nrev->{iid}.$nrev->{rev}", 'post'); } } diff --git a/lib/VNDB/Handler/Traits.pm b/lib/VNDB/Handler/Traits.pm index 1f3c2872..ea599ed1 100644 --- a/lib/VNDB/Handler/Traits.pm +++ b/lib/VNDB/Handler/Traits.pm @@ -104,8 +104,7 @@ sub traitpage { if(!@$chars) { p; br; br; txt mt '_traitp_nochars'; end; } - # not really cached at the moment - # p; br; txt mt '_traitp_cached'; end; + p; br; txt mt '_traitp_cached'; end; end 'div'; @$chars && $self->charBrowseTable($chars, $np, $f, "/i$trait?m=$f->{m}"); @@ -171,9 +170,6 @@ sub traitedit { } else { $self->dbTraitEdit($trait, %opts, upddate => $frm->{state} == 2 && $t->{state} != 2) if $trait; _set_childs_group($self, $trait, $group||$trait) if ($group||0) != ($t->{group}||0); - - # TEMPORARY SOLUTION! I'll investigate more efficient solutions and incremental updates whenever I have more data - $self->dbExec('SELECT traits_chars_calc()'); } $self->resRedirect("/i$trait", 'post'); return; -- cgit v1.2.3 From 000834947b9d7658639d4565c655a39cd3d68545 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 8 Apr 2011 19:46:52 +0200 Subject: Toggle [spoiler] tag visibility with global setting rather than mouse-over --- ChangeLog | 1 + data/script.js | 3 ++- lib/VNDB/Handler/Chars.pm | 2 +- lib/VNDBUtil.pm | 8 ++++---- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index a8ce144a..622a84f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ - Added 'select' all to wishlist and moved 'select all' down on notifies - Added char/tag/trait stats to database statistics box - Update traits_chars cache daily using Multi::Maintenance + - Toggle [spoiler] tag visibility with global setting rather than mouse-over - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser - Bugfix: properly announce chars and traits in Multi::IRC diff --git a/data/script.js b/data/script.js index 4fc3e49b..c2ede03c 100644 --- a/data/script.js +++ b/data/script.js @@ -2738,7 +2738,7 @@ if(byId('expandall')) { } -// charspoil handling (ugly) +// charspoil handling if(byId('charspoil_sel')) { var k = byClass('charspoil'); var h = byName(byId('charspoil_sel'), 'a'); @@ -2746,6 +2746,7 @@ if(byId('charspoil_sel')) { for(var i=0; i 1 : hasClass(k[i], 'charspoil_1') ? spoil < 1 : spoil < 2); for(var i=0; i 'chardesc', colspan => 2; h2 mt '_charp_description'; p; - lit bb2html $r->{desc}; + lit bb2html $r->{desc}, 0, 1; end; end; end; diff --git a/lib/VNDBUtil.pm b/lib/VNDBUtil.pm index a0469a1c..76290013 100644 --- a/lib/VNDBUtil.pm +++ b/lib/VNDBUtil.pm @@ -27,8 +27,7 @@ sub shorten { # v+, v+.+ # http://../ sub bb2html { - my $raw = shift; - my $maxlength = shift; + my($raw, $maxlength, $charspoil) = @_; $raw =~ s/\r//g; return '' if !$raw && $raw ne "0"; @@ -76,7 +75,8 @@ sub bb2html { next; } elsif($tag eq '[spoiler]') { push @open, 'spoiler'; - $result .= ''; + $result .= !$charspoil ? '' + : '<hidden by spoiler settings>'; + $result .= !$charspoil ? '' : ''; pop @open; next; } elsif($tag eq '[/quote]' && $open[$#open] eq 'quote') { -- cgit v1.2.3 From 32489742a0b37fe908d3445b45a398b9f3232390 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 9 Apr 2011 09:16:11 +0200 Subject: Cleaned up CSS code - Compacted most statements onto one line - Moved around a few blocks to better positions - Use .maintab for defaults instead of #maincontent - Removed some unecessary !importants --- ChangeLog | 1 + data/style.css | 1018 +++++++++++++++++--------------------------------------- 2 files changed, 305 insertions(+), 714 deletions(-) diff --git a/ChangeLog b/ChangeLog index 622a84f6..c099205d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ - Added char/tag/trait stats to database statistics box - Update traits_chars cache daily using Multi::Maintenance - Toggle [spoiler] tag visibility with global setting rather than mouse-over + - Cleaned up CSS code - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser - Bugfix: properly announce chars and traits in Multi::IRC diff --git a/data/style.css b/data/style.css index 1381114c..bc99fbcc 100644 --- a/data/style.css +++ b/data/style.css @@ -1,50 +1,15 @@ - - -* { - margin: 0; - padding: 0; -} - -body, td { - font: 11px "Tahoma"; -} -body { - $_bodybg$; - color: $maintext$ -} -a { - color: $maintext$; - text-decoration: none; -} -a:hover { - border-bottom: 1px dotted $maintext$; -} -table { - border-collapse: collapse; -} -table td { - vertical-align: top; - padding: 3px; -} -table tr.odd { - background: url($_boxbg$) repeat; -} -img { - border: none; -} - -#bgright { - position: absolute; - top: 0px; - right: 0px; - $_bgright$ -} - -#header { - position: absolute; - top: 80px; - left: 400px; -} +* { margin: 0; padding: 0; } +body, td { font: 11px "Tahoma"; } +body { $_bodybg$; color: $maintext$ } +a { color: $link$; text-decoration: none; } +a:hover { border-bottom: 1px dotted $maintext$; } +table { border-collapse: collapse; } +table td { vertical-align: top; padding: 3px; } +table tr.odd { background: url($_boxbg$) repeat; } +img { border: none; } + +#bgright { position: absolute; top: 0px; right: 0px; $_bgright$ } +#header { position: absolute; top: 80px; left: 400px; } #header h1, #header h1 a { font-family: "Futura", "Century New Gothic", "Arial", Serif; font-size: 24px; @@ -52,16 +17,8 @@ img { border: none!important; $_maintitle$ } - -#footer { - margin: 15px auto 0 auto; - text-align: center; - color: $footer$; -} -#footer a { - color: $footer$; - text-decoration: underline; -} +#footer { margin: 15px auto 0 auto; text-align: center; color: $footer$; } +#footer a { color: $footer$; text-decoration: underline; } #debug { position: fixed; @@ -77,42 +34,59 @@ img { #debug h2 { color: #f00!important; font-size: 20px; } #debug, #debug a { color: #fff!important; } -ul, ol { - margin-left: 35px; -} -p.locked { - float: right; - color: $standout$; - font-style: italic; - margin: 0!important; -} -b.grayedout { font-weight: normal; color: $grayedout$ } -i.grayedout { font-style: normal; color: $grayedout$ } -#maincontent h2 b { - font: 11px "Tahoma"; - font-weight: normal; -} -p.description { - margin: 10px 100px!important; -} -b.done { font-weight: normal; color: $statok$ } -b.todo { font-weight: normal; color: $statnok$ } -.clearfloat { - clear: both; - height: 0; -} -.hidden { - display: none!important -} +/* Warning/Notice Box */ +div.warning, div.notice { margin: 5px 10%; padding: 15px; background-color: $warnbg$; border: 1px solid $warnborder$; } +div.notice { background-color: $noticebg$; border: 1px solid $noticeborder$; } +div.warning ul, div.notice ul { margin-left: 0; } +div.warning li, div.notice li { margin-left: 20px; } +div.warning h2, div.notice h2 { font-size: 11px; font-weight: bold; margin: 0; } -b.spoiler, b.spoiler a { - color: #000!important; - background-color: #000; - font-weight: normal; +/* dropdown box */ +#dd_box { position: absolute; left: 0px; border: 1px solid $border$; background-color: $secbg$; z-index: 2 } +#dd_box ul { list-style-type: none; margin: 0; padding: 0 } +#dd_box li b { display: block; font-weight: normal; padding-left: 5px; } +#dd_box li i { display: block; font-style: normal; padding-left: 10px; padding-right: 5px } +#dd_box li a { display: block; padding-left: 10px; border: 0; padding-right: 5px } +#dd_box li a:hover { background: url($_boxbg$) repeat } + +/* dropdown search */ +#ds_box { + position: absolute; + top: 0; + border: 1px solid $border$; + border-top: none; + background-color: $secbg$; + cursor: pointer; + z-index: 2 } +#ds_box b { padding: 2px 0 0 10px; } +#ds_box tr.selected { background: url($_boxbg$) repeat; } +#ds_box table { width: 100%; } + + + +/* general text formatting */ + +ul, ol { margin-left: 35px; } +p.locked { float: right; color: $standout$; font-style: italic; margin: 0!important; } +b.grayedout { font-weight: normal; color: $grayedout$ } +i.grayedout { font-style: normal; color: $grayedout$ } +#maincontent h2 b { font: 11px "Tahoma"; font-weight: normal; } +p.description { margin: 10px 100px!important; } +b.done { font-weight: normal; color: $statok$ } +b.todo { font-weight: normal; color: $statnok$ } +p.center { text-align: center; } +b.future, +b.standout, +a.standout { font-weight: normal; color: $standout$; } +.clearfloat { clear: both; height: 0; } +.hidden { display: none!important } +.linethrough { text-decoration: line-through } +b.spoiler, b.spoiler a { color: #000!important; background-color: #000; font-weight: normal; } b.spoiler_shown { font-weight: normal } b.spoiler_shown a { color: $link$!important } + #maincontent div.quote { padding: 1px 5px; margin: 0px 10px; @@ -121,7 +95,6 @@ b.spoiler_shown a { color: $link$!important } border-left: 1px dotted $border$; text-align: left; } -.linethrough { text-decoration: line-through } pre { padding:1px 5px; margin: 5px 15px; @@ -136,13 +109,6 @@ pre { /***** general form markup *****/ -form, fieldset { - border: 0; - display: block; -} -legend { - display: none; -} input.text, input.submit, select, textarea { background-color: $secbg$; color: $maintext$; @@ -150,53 +116,46 @@ input.text, input.submit, select, textarea { font: 12px "Tahoma"; margin: 1px; } -optgroup option { - padding-left: 10px; - font-style: normal; -} -input.submit { - background: url($_boxbg$) repeat; - padding: 1px; -} -input.text, select { - width: 200px; -} -fieldset.submit { - width: 100%; - text-align: center; - margin: 5px; -} -fieldset.submit input { - width: 150px; -} -fieldset.submit h2 { - font-size: 11px!important; -} -fieldset.submit textarea { - margin: 0 20px 5px 20px; -} -table.formtable { - margin: 0 20px 20px 20px; -} -table.formtable td { - padding: 0; -} -table.formtable tr.newfield td { - padding-top: 5px; -} -table.formtable tr.newpart td { - padding-top: 20px; - font-weight: bold; -} -td.label, td.label label { - width: 90px; -} -td.label label { - display: block; -} -td.field label { - margin: 0 5px 0 5px; -} +form, fieldset { border: 0; display: block; } +legend { display: none; } +optgroup option { padding-left: 10px; font-style: normal; } +input.submit { background: url($_boxbg$) repeat; padding: 1px; } +input.text, select { width: 200px; } +fieldset.submit { width: 100%; text-align: center; margin: 5px; } +fieldset.submit input { width: 150px; } +fieldset.submit h2 { font-size: 11px!important; } +fieldset.submit textarea { margin: 0 20px 5px 20px; } +td.label, td.label label { width: 90px; } +td.label label { display: block; } +td.field label { margin: 0 5px 0 5px; } +table.formtable { margin: 0 20px 20px 20px; } +table.formtable td { padding: 0; } +table.formtable tr.newfield td { padding-top: 5px; } +table.formtable tr.newpart td { padding-top: 20px; font-weight: bold; } + + + + +/***** menu *****/ + + +#menulist a { color: $maintext$; text-decoration: none; } +#menulist a:hover { border-bottom: 1px dotted $maintext$; } +#menulist { position: absolute; left: 30px; top: 190px; width: 150px; } +#menulist div.menubox { margin: 0 0 10px 0; border: 1px solid $border$; background: url($_boxbg$) repeat; } +#menulist div.menubox div { padding: 2px 7px; } +#menulist h2 { border-bottom: 1px solid $border$; background: url($_boxbg$) repeat; padding: 1px 3px; } +#menulist h2, #menulist h2 a { font-size: 11px; color: $maintext$; } +#menulist h2 #lang_select { float: right; padding-top: 1px; } +#menulist dt { display: block; float: left; width: 93px; font-style: italic; } +#menulist dd { width: 40px; float: left; text-align: right; } +#menulist p { text-align: center; } +#menulist input.text { width: 100px; margin-left: 15px; } +#menulist input.submit { width: 90px; margin-left: 20px; } +#menulist #search input.text { width: 133px; margin: 0 0 3px 7px; font-style: italic; } +#menulist #search input.submit { display: none; } +#dd_box acronym { margin: 2px 5px 2px 0!important; } +#menulist .notifyget { display: inline-block; width: 125px; padding: 4px; background: $warnbg$; border: 1px solid $warnborder$; } @@ -211,114 +170,31 @@ td.field label { margin: 0; padding-bottom: 50px!important; } -#maincontent h1, #maincontent h2 { +.mainbox h1, .mainbox h2 { font-family: "Futura", "Century New Gothic", "Arial", Serif; font-weight: normal; font-size: 13px; } -#maincontent h1 { - color: $boxtitle$; - font-size: 19px; - margin: -5px 0 15px 0; -} -#maincontent h2.alttitle { - color: $alttitle$; - margin: -17px 0 15px 15px; - font-weight: normal; -} -#maincontent div.mainbox, #maincontent table.mainbox td { +div.mainbox, table.mainbox td { border: 1px solid $border$; margin: 21px 0 -10px 0; padding: 5px; background: url($_boxbg$) repeat; } -#maincontent .mainbox a { - color: $link$; -} -#maincontent p { - margin: 3px 20px; -} -#maincontent div div p, #maincontent div table p { - margin: 0; -} -#maincontent h2 { - font-weight: bold; - font-size: 14px; - margin: 10px 0 0 5px; -} -p.center { - text-align: center; -} -b.future, b.standout, a.standout { - font-weight: normal; - color: $standout$; -} - - - - -/***** menu *****/ - -#menulist { - position: absolute; - left: 30px; - top: 190px; - width: 150px; -} -#menulist div.menubox { - margin: 0 0 10px 0; - border: 1px solid $border$; - background: url($_boxbg$) repeat; -} -#menulist div.menubox div { - padding: 2px 7px; -} -#menulist h2 { - border-bottom: 1px solid $border$; - background: url($_boxbg$) repeat; - padding: 1px 3px; -} -#menulist h2, #menulist h2 a { - font-size: 11px; - color: $maintext$; -} -#menulist h2 #lang_select { - float: right; - padding-top: 1px; -} -#menulist dt { - display: block; - float: left; - width: 93px; - font-style: italic; -} -#menulist dd { - width: 40px; - float: left; - text-align: right; -} -#menulist p { - text-align: center; -} -#menulist input.text { - width: 100px; - margin-left: 15px; -} -#menulist input.submit { - width: 90px; - margin-left: 20px; -} -#menulist #search input.text { - width: 133px; - margin: 0 0 3px 7px; - font-style: italic; -} -#menulist #search input.submit { - display: none; -} -#dd_box acronym { margin: 2px 5px 2px 0!important; } -#menulist .notifyget { display: inline-block; width: 125px; padding: 4px; background: $warnbg$; border: 1px solid $warnborder$; } +.mainbox h1 { color: $boxtitle$; font-size: 19px; margin: -5px 0 15px 0; } +.mainbox h2.alttitle { color: $alttitle$; margin: -17px 0 15px 15px; font-weight: normal; } +.mainbox p { margin: 3px 20px; } +.mainbox div div p, +.mainbox div table p { margin: 0; } +.mainbox h2 { font-weight: bold; font-size: 14px; margin: 10px 0 0 5px; } +.mainbox.threelayout { border-collapse: separate; border-spacing: 10px; margin: 10px -10px -20px -10px; min-width: 100%; } +.mainbox.threelayout td { width: 32%; padding: 0 2px 10px 2px; } +.mainbox.threelayout h1 { margin: 0; font-size: 14px; font-weight: bold; } +.mainbox.threelayout h2 { font-size: 12px; margin-top: 3px; } +.mainbox.threelayout a.right { float: right; } +.mainbox.threelayout ul { list-style-type: none; margin-left: 10px; } +.mainbox.threelayout h1 a { color: $boxtitle$; } @@ -362,99 +238,33 @@ ul.maintabs.browsetabs li.left a { margin-left: 0; margin-right: 5px } /***** Homepage ******/ -#maincontent .mainbox.threelayout { - border-collapse: separate; - border-spacing: 10px; - margin: 10px -10px -20px -10px; - min-width: 100%; -} -#maincontent .mainbox.threelayout td { - width: 32%; - padding: 0 2px 10px 2px; -} -#maincontent .mainbox.threelayout h1 { - margin: 0; - font-size: 14px; - font-weight: bold; -} -#maincontent .mainbox.threelayout h2 { - font-size: 12px; - margin-top: 3px; -} -#maincontent .mainbox.threelayout a.right { - float: right; -} -#maincontent .mainbox.threelayout ul { - list-style-type: none; - margin-left: 10px; -} -p.screenshots { - text-align: center; - margin-top: 10px; - padding: 0; - height: 105px; -} -p.screenshots img { - margin: 2px; -} -#maincontent .mainbox.threelayout h1 a { - color: $boxtitle$; -} -a.feed { float: right } - +p.screenshots { text-align: center; margin-top: 10px; padding: 0; height: 105px; } +p.screenshots img { margin: 2px; } +a.feed { float: right } /***** Browsing ******/ -p.browseopts { - text-align: center; - padding: 2px; -} p.browseopts a { padding: 1px 3px; - color: $maintext$!important; + color: $maintext$; border: 1px solid $border$; margin: 0 2px; white-space: nowrap; } +p.browseopts { text-align: center; padding: 2px; } p.browseopts a.optselected, -p.browseopts a:hover { - border: 0; - padding: 2px 4px; -} -#maincontent div.mainbox.browse { - padding: 0; -} -div.mainbox.browse table { - width: 100%; -} -div.mainbox.browse table td.tc1 { - padding-left: 25px; -} -table thead td { - font-weight: bold; - background-color: $secbg$; -} -fieldset.search { - display: block; - width: 100%; - text-align: center; - margin: 0 0 10px 0; -} -fieldset.search .submit { - padding: 0 1px; -} -p#searchtabs { - height: 12px; - padding-right: 70px; -} -p#searchtabs a { - padding: 2px 6px 2px 6px; - margin: 0 2px; - color: $maintext$!important; -} +p.browseopts a:hover { border: 0; padding: 2px 4px; } +div.mainbox.browse { padding: 0; } +div.mainbox.browse table { width: 100%; } +div.mainbox.browse table td.tc1 { padding-left: 25px; } +table thead td { font-weight: bold; background-color: $secbg$; } +fieldset.search { display: block; width: 100%; text-align: center; margin: 0 0 10px 0; } +fieldset.search .submit { padding: 0 1px; } +p#searchtabs { height: 12px; padding-right: 70px; } +p#searchtabs a { padding: 2px 6px 2px 6px; margin: 0 2px; color: $maintext$; } p#searchtabs a:hover, p#searchtabs a.sel { border: 1px solid $secborder$; border-bottom: none; @@ -463,7 +273,10 @@ p#searchtabs a:hover, p#searchtabs a.sel { } #q { width: 450px } + + /* history browser */ + div.history table { table-layout: fixed } div.history td { white-space: nowrap } div.history td.tc1_1 { width: 60px; padding-left: 0; padding-right: 0; text-align: right } @@ -476,66 +289,28 @@ div.history td.tc4 b { margin-left: 10px } - - /***** Discussions ******/ /* threads page */ -#maincontent div.mainbox.thread { - padding: 0; -} -div.thread table { - width: 100%; -} -div.thread td { - border-bottom: 1px solid $border$; -} -div.thread td.tc1 { - width: 150px; - padding: 5px 10px; - border-right: 1px solid $border$; -} -div.thread td.tc2 { - padding: 10px 20px 10px 10px; -} -div.thread tr.deleted td { - padding: 1px 10px; -} -div.thread i.deleted { - font-style: normal; - color: $grayedout$; -} -div.thread i.lastmod { - float: right; - font-size: 10px; - color: $grayedout$; - margin: 0 -10px -5px 0; -} -div.thread i.edit { - float: right; - color: $grayedout$; - font-style: normal; - margin: -10px -10px 0 0; -} +#maincontent div.thread { padding: 0; } +div.thread table { width: 100%; } +div.thread td { border-bottom: 1px solid $border$; } +div.thread td.tc1 { width: 150px; padding: 5px 10px; border-right: 1px solid $border$; } +div.thread td.tc2 { padding: 10px 20px 10px 10px; } +div.thread tr.deleted td { padding: 1px 10px; } +div.thread i.deleted { font-style: normal; color: $grayedout$; } +div.thread i.lastmod { float: right; font-size: 10px; color: $grayedout$; margin: 0 -10px -5px 0; } +div.thread i.edit { float: right; color: $grayedout$; font-style: normal; margin: -10px -10px 0 0; } /* threads browser */ -div.mainbox.discussions td.tc4 { - text-align: right; -} -div.mainbox.discussions a.locked { - text-decoration: line-through; -} -div.mainbox.discussions b.boards { - padding-left: 10px; - font-weight: normal; -} -div.mainbox.discussions b.boards a { - color: $grayedout$!important; -} -div.discussions td.tc2 { width: 50px; } -div.discussions td.tc3 { width: 90px; } -div.discussions td.tc4 { width: 170px; } -#maincontent h1.boxtitle, #maincontent h1.boxtitle a { +div.mainbox.discussions td.tc4 { text-align: right; } +div.mainbox.discussions a.locked { text-decoration: line-through; } +div.mainbox.discussions b.boards { padding-left: 10px; font-weight: normal; } +div.mainbox.discussions b.boards a { color: $grayedout$; } +div.discussions td.tc2 { width: 50px; } +div.discussions td.tc3 { width: 90px; } +div.discussions td.tc4 { width: 170px; } +h1.boxtitle, h1.boxtitle a { font-family: "Futura", "Century New Gothic", "Arial", Serif; font-weight: bold; font-style: italic; @@ -547,119 +322,41 @@ div.discussions td.tc4 { width: 170px; } - /***** VN page *******/ -div.vndetails { - margin: 0 auto; - width: 800px; -} -div.vnimg { - float: left; - width: 250px; - margin: 0 10px; -} -div.vnimg i { - display: block; - width: 100%; - text-align: center; - font-size: 10px; -} -div.vnimg p { - text-align: center; - padding: 0px; - margin: 0; -} -.vndesc h2 { - margin: 5px 0 0 0!important; -} -.vndesc p { - padding: 0 0 0 5px; -} -p#nsfw_hid { - display: none; - cursor: pointer; -} -div.vndetails table { - float: left; - width: 530px; -} -div.vndetails table td.key { - width: 80px; -} -div.vndetails table dt { - float: left; - font-style: italic; -} -div.vndetails table dd { - margin-left: 90px; -} - -div.vndetails td.relations dt { - float: none; - font-style: normal; -} -div.vndetails td.relations dd { - margin-left: 15px; -} -div.vndetails td.anime b { - font-size: 8px; - font-weight: normal; - padding-right: 4px; -} -div#vntags { - margin: 15px 30px 0 30px; - border-top: 1px solid $border$; - padding: 1px 5% 0 5%; - text-align: center; -} -#vntags span { white-space: nowrap; margin-left: 15px; } -#vntags b { color: $grayedout$; font-weight: normal; font-size: 8px } -#tagops { - float: right; - text-align: right; - width: auto; - margin: 0 30px; -} -#tagops a { margin: 0 0 0 10px; border: 0; outline: none } -#tagops a.sec { border-left: 1px solid $border$; padding-left: 10px } -#maincontent #tagops a.tsel { color: $maintext$; } - -.releases table, #screenshots table { - width: 100%; -} -.releases tr.lang td, #screenshots tr.rel td { - background: url($_boxbg$) repeat; - font-weight: bold; -} -.releases td.tc1 { - padding-left: 30px; - width: 80px; -} -.releases td.tc2 { - text-align: center; - width: 50px; -} -.releases td.tc3 { - text-align: right; - padding: 0; - width: 90px; -} -.releases td.tc5 { - width: 70px; -} -.releases td.tc5 a { - color: $maintext$!important; - border: 0; -} -.releases td.tc6 { - text-align: right; - width: 25px; - padding: 0; -} -a.addnew { - float: right; -} +div.vndetails { margin: 0 auto; width: 800px; } +div.vnimg { float: left; width: 250px; margin: 0 10px; } +div.vnimg i { display: block; width: 100%; text-align: center; font-size: 10px; } +div.vnimg p { text-align: center; padding: 0px; margin: 0; } +.vndesc h2 { margin: 5px 0 0 0; } +.vndesc p { padding: 0 0 0 5px; } +p#nsfw_hid { display: none; cursor: pointer; } +div.vndetails table { float: left; width: 530px; } +div.vndetails table td.key { width: 80px; } +div.vndetails table dt { float: left; font-style: italic; } +div.vndetails table dd { margin-left: 90px; } +div.vndetails td.relations dt { float: none; font-style: normal; } +div.vndetails td.relations dd { margin-left: 15px; } +div.vndetails td.anime b { font-size: 8px; font-weight: normal; padding-right: 4px; } +div#vntags { margin: 15px 30px 0 30px; border-top: 1px solid $border$; padding: 1px 5% 0 5%; text-align: center; } +#vntags span { white-space: nowrap; margin-left: 15px; } +#vntags b { color: $grayedout$; font-weight: normal; font-size: 8px } +#tagops { float: right; text-align: right; width: auto; margin: 0 30px; } +#tagops a { margin: 0 0 0 10px; border: 0; outline: none } +#tagops a.sec { border-left: 1px solid $border$; padding-left: 10px } +#tagops a.tsel { color: $maintext$; } + +.releases table, +#screenshots table { width: 100%; } +.releases tr.lang td, +#screenshots tr.rel td { background: url($_boxbg$) repeat; font-weight: bold; } +.releases td.tc1 { padding-left: 30px; width: 80px; } +.releases td.tc2 { text-align: center; width: 50px; } +.releases td.tc3 { text-align: right; padding: 0; width: 90px; } +.releases td.tc5 { width: 70px; } +.releases td.tc5 a { color: $maintext$; border: 0; } +.releases td.tc6 { text-align: right; width: 25px; padding: 0; } +a.addnew { float: right; } #screenshots p.rel { background: url($_boxbg$) repeat; @@ -677,28 +374,19 @@ a.addnew { #screenshots p.nsfwtoggle { float: right; margin: 0; } -#dd_box { position: absolute; left: 0px; border: 1px solid $border$; background-color: $secbg$; z-index: 2 } -#dd_box ul { list-style-type: none; margin: 0; padding: 0 } -#dd_box li b { display: block; font-weight: normal; padding-left: 5px; } -#dd_box li i { display: block; font-style: normal; padding-left: 10px; padding-right: 5px } -#dd_box li a { display: block; padding-left: 10px; color: $link$; border: 0; padding-right: 5px } -#dd_box li a:hover { background: url($_boxbg$) repeat } - - - /***** Vote stats ****/ -.votestats { width: 610px; margin: 0 auto; } -.votegraph { float: left; margin-right: 20px } +.votestats { width: 610px; margin: 0 auto; } +.votegraph { float: left; margin-right: 20px } .votegraph td { padding: 0 2px; } .votegraph td.number { text-align: right } .votegraph td div { float: left; height: 14px; background-color: $border$; margin-right: 2px; padding: 0; } -.votestats thead td { background: transparent; text-align: center; padding: 2px; } +.votestats thead td { background: transparent; text-align: center; padding: 2px; } .votestats tfoot td { text-align: right } -.votestats div { text-align: center; padding-top: 5px; } +.votestats div { text-align: center; padding-top: 5px; } -.recentvotes { width: 300px } +.recentvotes { width: 300px } .recentvotes thead tr td b { font-weight: normal; padding-left: 5px } @@ -715,52 +403,25 @@ a.addnew { #jt_box_vn_rel td.tc_vn input { width: 280px; } #jt_box_vn_rel td.tc_rel select { width: 130px; } -#ds_box { - position: absolute; - top: 0; - border: 1px solid $border$; - border-top: none; - background-color: $secbg$; - cursor: pointer; - z-index: 2 -} -#ds_box b { - padding: 2px 0 0 10px; -} -#ds_box tr.selected { - background: url($_boxbg$) repeat; -} -#ds_box table { - width: 100%; -} - -#jt_box_vn_img div.img { - float: left; - height: 400px; - padding-right: 20px; -} -#jt_box_vn_img h2 { - margin: 0; -} +#jt_box_vn_img div.img { float: left; height: 400px; padding-right: 20px; } +#jt_box_vn_img h2 { margin: 0; } #jt_box_vn_scr table { width: 95% } -#scr_table td { height: 108px; border-top: 1px solid #258; padding: 0; padding-right: 5px } -#scr_table td.thumb { width: 136px; vertical-align: middle } -#scr_table select { width: 400px; } -div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px; position: absolute; display: none; left: 0; top: 0; } - - +#scr_table td { height: 108px; border-top: 1px solid #258; padding: 0; padding-right: 5px } +#scr_table td.thumb { width: 136px; vertical-align: middle } +#scr_table select { width: 400px; } +div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px; position: absolute; display: none; left: 0; top: 0; } /****** VN browse ********/ .vnbrowse thead .tc_s { padding-left: 30px } -.vnbrowse .tc_s { width: 65px } -.vnbrowse .tc2 { text-align: right; padding: 0; } -.vnbrowse .tc3 { padding: 0; } -.vnbrowse .tc5 { text-align: right; padding-right: 10px } -.vnbrowse .tc6 { width: 80px } +.vnbrowse .tc_s { width: 65px } +.vnbrowse .tc2 { text-align: right; padding: 0; } +.vnbrowse .tc3 { padding: 0; } +.vnbrowse .tc5 { text-align: right; padding-right: 10px } +.vnbrowse .tc6 { width: 80px } #filselect { text-align: center; display: block; @@ -788,22 +449,11 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px #prodrel td.tc6 { width: 25px; text-align: right; padding: 0; } #expandprodrel { float: right; font-weight: bold; padding-bottom: 2px; border: none } -.producerbrowse ul { - float: left; - margin-top: -5px; - margin-left: 3%; - width: 28%; -} -.producerbrowse ul li { - list-style-type: none; -} -.producerbrowse ul li acronym { - margin-right: 5px; - margin-top: 1px; -} -.producerbrowse { - padding-bottom: 10px!important -} +div.producerbrowse { padding-bottom: 10px } +.producerbrowse ul { float: left; margin-top: -5px; margin-left: 3%; width: 28%; } +.producerbrowse ul li { list-style-type: none; } +.producerbrowse ul li acronym { margin-right: 5px; margin-top: 1px; } + /***** Producer edit *****/ @@ -820,30 +470,27 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px /***** Release page *****/ -.release table { - width: 400px; - margin: 0 auto; -} -.release .key { - width: 70px; -} +.release table { width: 400px; margin: 0 auto; } +.release .key { width: 70px; } + + +/* Release edit */ -/* edit */ -.platforms { padding-left: 20px; } +.platforms { padding-left: 20px; } .platforms span { display: block; float: left; width: 150px; } -#jt_box_rel_format h2 { clear: left; padding-top: 10px; } -#media_div select.qty { width: 90px; } +#jt_box_rel_format h2 { clear: left; padding-top: 10px; } +#media_div select.qty { width: 90px; } #media_div select.medium { width: 150px } -#media_div { padding-left: 20px; } -#media_div span { display: block } +#media_div { padding-left: 20px; } +#media_div span { display: block } #jt_box_rel_vn h2, #jt_box_rel_prod h2 { clear: left; padding-top: 10px; } #jt_box_rel_vn div, #jt_box_rel_vn table, #jt_box_rel_prod div, #jt_box_rel_prod table { margin-left: 20px } #jt_box_rel_vn input, #jt_box_rel_prod input { margin-right: 10px; width: 295px } #jt_box_rel_vn .tc_title, #jt_box_rel_prod .tc_name { width: 310px; padding: 2px } -#jt_box_rel_prod .tc_role select { width: 100px; margin-right: 10px; } +#jt_box_rel_prod .tc_role select { width: 100px; margin-right: 10px; } @@ -860,38 +507,40 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px div.chardetails { margin: 0 auto; width: 800px; } div.charimg { float: left; width: 250px; margin: 0 10px; text-align: center } div.charimg p { text-align: center; padding: 0px; margin: 0; } -.chardesc h2 { margin: 0!important; } +.chardesc h2 { margin: 0; } .chardesc p { padding: 0 0 0 5px; } -div.chardetails table { float: left; width: 530px; } +div.chardetails table { float: left; width: 530px; } div.chardetails table td.key { width: 80px; } -div.chardetails.charsep { padding-top: 5px; margin-top: 5px; border-top: 1px solid $border$ } -#charspoil_sel { clear: right; float: right; } -#charspoil_sel a { margin: 0 0 0 10px; border: 0; outline: none } -#maincontent #charspoil_sel a.sel { color: $maintext$; } +div.chardetails.charsep { padding-top: 5px; margin-top: 5px; border-top: 1px solid $border$ } +#charspoil_sel { clear: right; float: right; } +#charspoil_sel a { margin: 0 0 0 10px; border: 0; outline: none } +#charspoil_sel a.sel { color: $maintext$; } /***** Char edit *****/ + #jt_box_chare_img div.img { float: left; height: 300px; padding-right: 20px; } -#jt_box_chare_img h2 { margin: 0; } +#jt_box_chare_img h2 { margin: 0; } #jt_box_chare_traits table { margin-bottom: 10px; margin-left: 10px; } #jt_box_chare_traits h2 { margin: 0 0 3px 0px; } -#jt_box_chare_traits td.tc_name { width: 200px } +#jt_box_chare_traits td.tc_name { width: 200px } #jt_box_chare_traits td.tc_name input { width: 280px; } -#jt_box_chare_traits td.tc_spoil { width: 80px; } +#jt_box_chare_traits td.tc_spoil { width: 80px; } #jt_box_chare_vns table { margin-bottom: 10px; margin-left: 10px; } #jt_box_chare_vns h2 { margin: 0 0 3px 0px; } -#jt_box_chare_vns td.tc_vn { font-weight: bold; padding: 5px 0 3px 0 } -#jt_box_chare_vns td.tc_vn i{ font-weight: normal; padding-left: 5px; font-style: normal } -#jt_box_chare_vns td.tc_rel { width: 340px; padding-left: 15px } -#jt_box_chare_vns td.tc_rel select { width: 340px; } +#jt_box_chare_vns td.tc_vn { font-weight: bold; padding: 5px 0 3px 0 } +#jt_box_chare_vns td.tc_vn i { font-weight: normal; padding-left: 5px; font-style: normal } +#jt_box_chare_vns td.tc_rel { width: 340px; padding-left: 15px } +#jt_box_chare_vns td.tc_rel select { width: 340px; } #jt_box_chare_vns td.tc_rol, -#jt_box_chare_vns td.tc_rol select { width: 150px } +#jt_box_chare_vns td.tc_rol select { width: 150px } #jt_box_chare_vns td.tc_spl, -#jt_box_chare_vns td.tc_spl select { width: 100px } -#jt_box_chare_vns td.tc_del { padding-left: 5px } +#jt_box_chare_vns td.tc_spl select { width: 100px } +#jt_box_chare_vns td.tc_del { padding-left: 5px } #jt_box_chare_vns td.tc_vnadd input { width: 280px } + /***** Char browse *****/ div.charb table { table-layout: fixed } @@ -902,19 +551,19 @@ div.charb td.tc2 b { margin-left: 10px } div.charb td.tc2 b a { color: $grayedout$!important } + /***** Documentation pages *****/ -.docs { padding: 0 15% 20px 15%; } -.docs h3 { margin-top: 30px; font-size: 14px } -.docs h4 { margin-top: 15px; font-size: 12px } -.docs dd { padding-bottom: 5px; margin-left: 120px; } -.docs dt { float: left } -.docs ul.index { display: block; float: right; width: 150px; padding: 2px; margin: 0 0 10px 5px; background: url($_boxbg$) repeat; border: 1px solid $border$; } -.docs ul.index li { list-style-type: none; } +.docs { padding: 0 15% 20px 15%; } +.docs h3 { margin-top: 30px; font-size: 14px } +.docs h4 { margin-top: 15px; font-size: 12px } +.docs dd { padding-bottom: 5px; margin-left: 120px; } +.docs dt { float: left } +.docs ul.index { display: block; float: right; width: 150px; padding: 2px; margin: 0 0 10px 5px; background: url($_boxbg$) repeat; border: 1px solid $border$; } +.docs ul.index li { list-style-type: none; } .docs ul.index li a { margin: 0 0 0 10px; } -.docs .retired { text-decoration: line-through; } -.docs dt b { color: $grayedout$; font-weight: normal; font-style: normal; font-size: 12px; } - +.docs .retired { text-decoration: line-through; } +.docs dt b { color: $grayedout$; font-weight: normal; font-style: normal; font-size: 12px; } @@ -926,7 +575,7 @@ div.votelist td.tc2 { width: 50px; text-align: right; padding-right: 10px } /***** Wishlist browser ******/ -.wishlist .tc1 { padding-top: 0; padding-bottom: 0; } +.wishlist .tc1 { padding-top: 0; padding-bottom: 0; } .wishlist tfoot td { padding: 0 0 0 25px } @@ -940,33 +589,28 @@ div.votelist td.tc2 { width: 50px; text-align: right; padding-right: 10px } .browse.rlist .tc3_5 b { margin-left: 10px } .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 } +.browse.rlist .relhid .tc6 { padding-left: 15px; width: auto } /***** User notifications *****/ -.browse.notifies td.tc1 { width: 14px } -.browse.notifies td.tc3 { width: 90px } -.browse.notifies td.tc4 { width: 60px } +.browse.notifies td.tc1 { width: 14px } +.browse.notifies td.tc3 { width: 90px } +.browse.notifies td.tc4 { width: 60px } .browse.notifies tbody td.tc5 { color: $grayedout$; cursor: pointer } -.browse.notifies td.tc5 i { font-style: normal; color: $maintext$ } -.browse.notifies .unread td { font-weight: bold } -.browse.notifies tfoot td { padding: 0 0 0 25px } +.browse.notifies td.tc5 i { font-style: normal; color: $maintext$ } +.browse.notifies .unread td { font-weight: bold } +.browse.notifies tfoot td { padding: 0 0 0 25px } /***** Userpage *****/ -.userpage table { - width: 400px; - margin: 0 auto; -} -.userpage .key { - width: 70px; -} +.userpage table { width: 400px; margin: 0 auto; } +.userpage .key { width: 70px; } /***** User posts browser ****/ @@ -983,20 +627,22 @@ div.uposts td.tc4 b { margin-left: 10px } /***** Tag page *****/ -.tagtree { margin-left: 20px; margin-top: -20px; list-style-type: none; } -.tagtree li { float: left; width: 200px; margin-top: 10px; } -.tagtree li li { float: none; width: auto; margin-top: 0; } -.tagtree ul { margin-left: 10px; list-style-type: none; } +.tagtree { margin-left: 20px; margin-top: -20px; list-style-type: none; } +.tagtree li { float: left; width: 200px; margin-top: 10px; } +.tagtree li li { float: none; width: auto; margin-top: 0; } +.tagtree ul { margin-left: 10px; list-style-type: none; } .tagvnlist .tc1 { width: 105px; } .tagvnlist .tc1 i { font-style: normal; font-size: 8px } .tagvnlist .tc3 { text-align: right; padding: 0; } .tagvnlist .tc4 { padding: 0; } .tagvnlist .tc6 { text-align: right; padding-right: 10px; } + /***** Tag/trait list (/g/list, /i/list) *****/ .browse.taglist .tc1 { width: 80px } + /***** Tag links *****/ .browse.taglinks .tc1 { width: 70px } @@ -1006,68 +652,39 @@ div.uposts td.tc4 b { margin-left: 10px } .browse.taglinks .ignored .taglvl.taglvl0 { color: $grayedout$!important } .browse.taglinks .setfil { font-size: 8px; padding-right: 3px } + /***** VN tagmod *****/ #jt_box_tagmod .formtable table td { padding: 1px 5px } -table.tgl tfoot td { padding-top: 20px!important; } -table.tgl .tc_you { border-right: 1px solid $border$; border-left: 1px solid $border$; width: 150px; text-align: center } -table.tgl .tc_others { border-left: 1px solid $border$; width: 150px; text-align: center } -table.tgl .tc_tagname { min-width: 200px; border-right: 1px solid $border$ } +table.tgl tfoot td { padding-top: 20px!important; } +table.tgl .tc_you { border-right: 1px solid $border$; border-left: 1px solid $border$; width: 150px; text-align: center } +table.tgl .tc_others { border-left: 1px solid $border$; width: 150px; text-align: center } +table.tgl .tc_tagname { min-width: 200px; border-right: 1px solid $border$ } table.tgl tbody .tc_tagname { padding-left: 15px!important } -table.tgl .tc_myvote { padding-left: 30px!important } -table.tgl .tc_myover { padding: 0!important } -table.tgl .tc_myspoil { border-right: 1px solid $border$; padding-right: 30px!important; text-align: right; padding-left: 10px!important; cursor: pointer } -table.tgl .tc_allvote { padding-left: 30px!important; } -table.tgl .tc_allvote i { font-style: normal; font-size: 8px } -table.tgl .tc_allspoil { text-align: right; padding-right: 15px!important; } -table.tgl .tagmod_cat td { font-weight: bold } -.taglvl { display: block; float: left; width: 8px; height: 12px; border: 1px solid $border$; font-size: 1px; color: $maintext$!important } -.taglvl0 { width: 15px; border: none!important; font-size: 10px; text-align: center; } -div.taglvl0 { font-size: 8px; width: 20px!important } -div.taglvl { border: none!important; width: 10px; height: 14px } -a.taglvl:hover { border-bottom: 1px solid transparent!important } +table.tgl .tc_myvote { padding-left: 30px!important } +table.tgl .tc_myover { padding: 0!important } +table.tgl .tc_myspoil { border-right: 1px solid $border$; padding-right: 30px!important; text-align: right; padding-left: 10px!important; cursor: pointer } +table.tgl .tc_allvote { padding-left: 30px!important; } +table.tgl .tc_allvote i { font-style: normal; font-size: 8px } +table.tgl .tc_allspoil { text-align: right; padding-right: 15px!important; } +table.tgl .tagmod_cat td { font-weight: bold } +.taglvl { display: block; float: left; width: 8px; height: 12px; border: 1px solid $border$; font-size: 1px; color: $maintext$!important } +.taglvl0 { width: 15px; border: none; font-size: 10px; text-align: center; } +div.taglvl0 { font-size: 8px; width: 20px!important } +div.taglvl { border: none; width: 10px; height: 14px } +a.taglvl:hover { border-bottom: 1px solid transparent } .taglvlsel.taglvl-3 { background-color: #f00; border-color: #f00 } .taglvlsel.taglvl-2 { background-color: #f40; border-color: #f40 } .taglvlsel.taglvl-1 { background-color: #f80; border-color: #f80 } -.taglvlsel.taglvl1 { background-color: #cf0; border-color: #cf0 } -.taglvlsel.taglvl2 { background-color: #8f0; border-color: #8f0 } -.taglvlsel.taglvl3 { background-color: #0f0; border-color: #0f0 } - - - - -/***** Warning/Notice Box *****/ - -div.warning, div.notice { - margin: 5px 10%; - padding: 15px; - background-color: $warnbg$; - border: 1px solid $warnborder$; -} -div.notice { - background-color: $noticebg$; - border: 1px solid $noticeborder$; -} -div.warning ul, div.notice ul { - margin-left: 0; -} -div.warning li, div.notice li { - margin-left: 20px; -} -#maincontent div.warning h2, #maincontent div.notice h2 { - font-size: 11px; - font-weight: bold; - margin: 0; -} +.taglvlsel.taglvl1 { background-color: #cf0; border-color: #cf0 } +.taglvlsel.taglvl2 { background-color: #8f0; border-color: #8f0 } +.taglvlsel.taglvl3 { background-color: #0f0; border-color: #0f0 } /****** Revision information ******/ -div.revision { - padding-bottom: 10px!important; -} div.revision div.rev, div.revision table { border: 1px solid $border$; margin: 0 auto; @@ -1075,41 +692,16 @@ div.revision div.rev, div.revision table { background-color: $secbg$; clear: both; } -div.revision table thead tr td { - background-color: transparent!important; - text-align: center; - font-weight: normal; -} -div.revision table td { - border-right: 1px solid $border$; - padding: 5px; -} -div.revision td.tcval { - width: 44%; -} -div.revision div.rev { - padding: 5px; - text-align: center; -} -.diff_add { - font-weight: normal; - background-color: $diffadd$; -} -.diff_del { - font-weight: normal; - background-color: $diffdel$; -} -div.revision .next { - float: right; - margin-right: 5%; -} -div.revision .prev { - float: left; - margin-left: 5%; -} -div.revision .item { - text-align: center; -} +div.revision { padding-bottom: 10px; } +div.revision table thead tr td { background-color: transparent!important; text-align: center; font-weight: normal; } +div.revision table td { border-right: 1px solid $border$; padding: 5px; } +div.revision td.tcval { width: 44%; } +div.revision div.rev { padding: 5px; text-align: center; } +.diff_add { font-weight: normal; background-color: $diffadd$; } +.diff_del { font-weight: normal; background-color: $diffdel$; } +div.revision .next { float: right; margin-right: 5%; } +div.revision .prev { float: left; margin-left: 5%; } +div.revision .item { text-align: center; } @@ -1124,12 +716,12 @@ div#iv_view { padding: 5px; text-align: center; } -#iv_view a { border: 0; font-weight: bold; font-size: 12px } +#iv_view a { border: 0; font-weight: bold; font-size: 12px } #iv_view img { cursor: pointer } -#ivclose { float: right; padding-left: 10px } -#ivnext { padding-left: 5px; } -#ivprev { padding-right: 5px; } -#ivfull { float: left; padding-right: 10px; } +#ivclose { float: right; padding-left: 10px } +#ivnext { padding-left: 5px; } +#ivprev { padding-right: 5px; } +#ivfull { float: left; padding-right: 10px; } #ivimgload { position: absolute; display: block; @@ -1145,7 +737,6 @@ div#iv_view { - /****** filter selector *****/ div#fil_div { @@ -1158,23 +749,22 @@ div#fil_div { width: 600px; text-align: center; } -#fil_div a.close { float: right; color: $link$; border: 0; font-weight: bold } -#fil_div p.browseopts { padding: 2px 50px; line-height: 23px } -#fil_div .browseopts a { outline: none } +#fil_div a.close { float: right; border: 0; font-weight: bold } +#fil_div p.browseopts { padding: 2px 50px; line-height: 23px } +#fil_div .browseopts a { outline: none; color: $maintext$ } #fil_div .browseopts a.active { font-weight: bold } -#fil_div b.ruler { display: block; margin: auto; width: 93%; height: 1px; border-bottom: 1px solid $border$; margin-bottom: 5px } -#fil_div h3 { width: 100%; text-align: center; font-size: 11px } -#fil_div table { width: 93%; text-align: left; margin: 0 auto 5px auto } +#fil_div b.ruler { display: block; margin: auto; width: 93%; height: 1px; border-bottom: 1px solid $border$; margin-bottom: 5px } +#fil_div h3 { width: 100%; text-align: center; font-size: 11px } +#fil_div table { width: 93%; text-align: left; margin: 0 auto 5px auto } #fil_div table td.label label { width: 120px } #fil_div table td.label b { display: block; font-weight: normal; padding: 10px 5px 0 0 } #fil_div table td.check { width: 15px } #fil_div label.active { font-weight: bold } -#fil_div .opts a { border: 0; outline: none; color: $link$ } +#fil_div .opts a { border: 0; outline: none } #fil_div .opts b { margin: 0 7px; font-weight: normal } #fil_div .opts a.tsel { color: $maintext$; } -#filselect i { font-style: normal } -#fil_div table ul { margin: 0 0 0 15px } -#fil_div table ul a { color: $link$ } +#filselect i { font-style: normal } +#fil_div table ul { margin: 0 0 0 15px } -- cgit v1.2.3 From 07fb57d8c4736f1034946079584695851d910ca0 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 9 Apr 2011 13:35:33 +0200 Subject: affiliates: Added very basic support for sponsored "buy now" links --- data/script.js | 15 +++++++++++++++ data/style.css | 9 +++++++++ lib/VNDB/DB/Releases.pm | 2 +- lib/VNDB/Handler/VNPage.pm | 30 ++++++++++++++++++++++++++++++ util/sql/schema.sql | 15 +++++++++++++++ util/updates/update_2.20.sql | 19 +++++++++++++++++++ 6 files changed, 89 insertions(+), 1 deletion(-) diff --git a/data/script.js b/data/script.js index c2ede03c..a9e79aa1 100644 --- a/data/script.js +++ b/data/script.js @@ -2763,6 +2763,21 @@ if(byId('charspoil_sel')) { } +// mouse-over price information / disclaimer +if(byId('buynow')) { + var l = byClass(byId('buynow'), 'acronym', 'pricenote'); + for(var i=0; i{relations}}; _anime($self, \$i, $v) if @{$v->{anime}}; _useroptions($self, \$i, $v) if $self->authInfo->{id}; + _affiliate_links($self, $r); Tr; td class => 'vndesc', colspan => 2; @@ -404,6 +405,35 @@ sub _useroptions { } +sub _affiliate_links { + my($self, $r) = @_; + return if !keys @$r; + my %r = map +($_->{id}, $_), @$r; + my $links = $self->dbAffiliateGet(rids => [ keys %r ]); + return if !@$links; + + $links = [ sort { $b->{priority} <=> $a->{priority} } @$links ]; + my $en = VNDB::L10N->get_handle('en'); + + Tr; td colspan => 2, id => 'buynow'; # don't call it "affiliate", most adblock filters have that included >_> + h1; a href => $links->[0]{url}, 'Buy now!'; end; + ul; + for my $link (@$links) { + li; a href => $link->{url}; + use utf8; + txt '→ '; + txt $link->{version} || join(', ', map $en->maketext("_lang_$_"), @{$r{$link->{rid}}{languages}}).' version'; + txt ' '; + acronym class => 'pricenote', title => sprintf('Last updated: %s.', $en->age($link->{lastfetch})), "for $link->{price}*" + if $link->{price}; + txt " at $self->{affiliates}[$link->{affiliate}]{name}."; + end; end; + } + end; + end; end; +} + + sub _releases { my($self, $v, $r) = @_; diff --git a/util/sql/schema.sql b/util/sql/schema.sql index 39e9351a..d780bec8 100644 --- a/util/sql/schema.sql +++ b/util/sql/schema.sql @@ -1,5 +1,18 @@ +-- affiliate_links +CREATE TABLE affiliate_links ( + id SERIAL PRIMARY KEY, + rid integer NOT NULL, + hidden boolean NOT NULL DEFAULT false, + priority smallint NOT NULL DEFAULT 0, + affiliate smallint NOT NULL DEFAULT 0, + url varchar NOT NULL, + version varchar NOT NULL DEFAULT '', + lastfetch timestamptz, + price varchar NOT NULL DEFAULT '' +); + -- anime CREATE TABLE anime ( id integer NOT NULL PRIMARY KEY, @@ -452,6 +465,7 @@ CREATE TABLE wlists ( +ALTER TABLE affiliate_links ADD FOREIGN KEY (rid) REFERENCES releases (id); ALTER TABLE changes ADD FOREIGN KEY (requester) REFERENCES users (id) ON DELETE SET DEFAULT; ALTER TABLE chars ADD FOREIGN KEY (latest) REFERENCES chars_rev (id) DEFERRABLE INITIALLY DEFERRED; ALTER TABLE chars_rev ADD FOREIGN KEY (id) REFERENCES changes (id); @@ -521,6 +535,7 @@ ALTER TABLE wlists ADD FOREIGN KEY (uid) REFERENCES users ALTER TABLE wlists ADD FOREIGN KEY (vid) REFERENCES vn (id); +CREATE INDEX affiliate_links_rid ON affiliate_links (rid) WHERE NOT hidden; CREATE INDEX releases_vn_vid ON releases_vn (vid); CREATE INDEX tags_vn_date ON tags_vn (date); CREATE UNIQUE INDEX chars_vns_pkey ON chars_vns (cid, vid, COALESCE(rid, 0)); diff --git a/util/updates/update_2.20.sql b/util/updates/update_2.20.sql index 28efd713..9ee38b07 100644 --- a/util/updates/update_2.20.sql +++ b/util/updates/update_2.20.sql @@ -22,3 +22,22 @@ CREATE TRIGGER stats_cache_edit AFTER UPDATE ON tags CREATE TRIGGER stats_cache_new AFTER INSERT ON traits FOR EACH ROW WHEN (NEW.state = 2) EXECUTE PROCEDURE update_stats_cache(); CREATE TRIGGER stats_cache_edit AFTER UPDATE ON traits FOR EACH ROW WHEN (OLD.state IS DISTINCT FROM NEW.state) EXECUTE PROCEDURE update_stats_cache(); + + +CREATE TABLE affiliate_links ( + id SERIAL PRIMARY KEY, + rid integer NOT NULL REFERENCES releases (id), + hidden boolean NOT NULL DEFAULT false, -- to hide a link for some reason + priority smallint NOT NULL DEFAULT 0, -- manual ordering when competing on a VN page, usually not necessary + affiliate smallint NOT NULL DEFAULT 0, -- index to a semi-static array in data/config.pl + url varchar NOT NULL, + version varchar NOT NULL DEFAULT '', -- "x edition" or "x version", default used is " version" + lastfetch timestamptz, -- last update of price + price varchar NOT NULL DEFAULT '' -- formatted, including currency, e.g. "$50" or "€34.95 / $50.46" +); + +CREATE INDEX affiliate_links_rid ON affiliate_links (rid) WHERE NOT hidden; + +--INSERT INTO affiliate_links (rid, priority, affiliate, url, version, lastfetch, price) VALUES +-- (175, 1, 0, 'http://www.jbox.com/product/PCG4776', 'Original all-ages edition (Japanese)', NOW(), '$110.00'), +-- (8124, 0, 0, 'http://www.jbox.com/product/PSPLB001', 'Converted edition (PSP, Japanese)', NOW(), '$78.00'); -- cgit v1.2.3 From 715f47095c359d0a9c25ea8b6c3af635cc0d8658 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 9 Apr 2011 16:18:27 +0200 Subject: affiliates: Added simple admin interface + default_prio The lastfetch/price columns can't be modified at the moment. --- ChangeLog | 1 + data/global.pl | 14 ++--- lib/VNDB/DB/Affiliates.pm | 54 ++++++++++++++++++ lib/VNDB/Handler/Affiliates.pm | 123 +++++++++++++++++++++++++++++++++++++++++ lib/VNDB/Handler/VNPage.pm | 3 +- util/updates/update_2.20.sql | 1 + 6 files changed, 188 insertions(+), 8 deletions(-) create mode 100644 lib/VNDB/DB/Affiliates.pm create mode 100644 lib/VNDB/Handler/Affiliates.pm diff --git a/ChangeLog b/ChangeLog index c099205d..734689ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ 2.20 - ? + - Added support for sponsored links on VN pages - Order the VNs listed on char browser by release date - Order the traits groups on /i by their 'order' column - Use same browsing-table on trait pages and char browser diff --git a/data/global.pl b/data/global.pl index 5fd2bf85..c985b8ea 100644 --- a/data/global.pl +++ b/data/global.pl @@ -32,13 +32,13 @@ our %S = (%S, ch_size => [ 256, 300 ], # max. w*h of char images cv_size => [ 256, 400 ], # max. w*h of cover images user_ranks => [ - # allowed actions # DB number - [qw| hist |], # 0 - [qw| hist |], # 1 - [qw| hist board |], # 2 - [qw| hist board edit tag |], # 3 - [qw| hist board boardmod edit charedit tag mod lock del tagmod |], # 4 - [qw| hist board boardmod edit charedit tag mod lock del tagmod usermod |], # 5 + # allowed actions # DB number + [qw| hist |], # 0 + [qw| hist |], # 1 + [qw| hist board |], # 2 + [qw| hist board edit tag |], # 3 + [qw| hist board boardmod edit charedit tag mod lock del tagmod |], # 4 + [qw| hist board boardmod edit charedit tag mod lock del tagmod usermod affiliate |], # 5 ], languages => [qw|cs da de en es fi fr hu it ja ko nl no pl pt-br pt-pt ru sk sv tr vi zh|], producer_types => [qw|co in ng|], diff --git a/lib/VNDB/DB/Affiliates.pm b/lib/VNDB/DB/Affiliates.pm new file mode 100644 index 00000000..2aa891ce --- /dev/null +++ b/lib/VNDB/DB/Affiliates.pm @@ -0,0 +1,54 @@ + +package VNDB::DB::Affiliates; + +use strict; +use warnings; +use POSIX 'strftime'; +use Exporter 'import'; + +our @EXPORT = qw|dbAffiliateGet dbAffiliateEdit dbAffiliateDel dbAffiliateAdd|; + + +# options: id rids affiliate hide_hidden +# what: release +sub dbAffiliateGet { + my($self, %o) = @_; + + my %where = ( + $o{id} ? ('id = ?' => $o{id}) : (), + $o{rids} ? ('rid IN(!l)' => [$o{rids}]) : (), + defined($o{affiliate}) ? ('affiliate = ?' => $o{affiliate}) : (), + $o{hide_hidden} ? ('NOT hidden' => 1) : (), + ); + + my $join = $o{what} ? 'JOIN releases r ON r.id = af.rid JOIN releases_rev rr ON rr.id = r.latest' : ''; + my $select = $o{what} ? ', rr.title' : ''; + + return $self->dbAll("SELECT af.id, af.rid, af.hidden, af.priority, af.affiliate, af.url, af.version, extract('epoch' from af.lastfetch) as lastfetch, af.price$select + FROM affiliate_links af $join !W", \%where); +} + + +sub dbAffiliateDel { + my($self, $id) = @_; + $self->dbExec('DELETE FROM affiliate_links WHERE id = ?', $id); +} + + +sub dbAffiliateEdit { + my($self, $id, %ops) = @_; + my %set; + exists($ops{$_}) && ($set{"$_ = ?"} = $ops{$_}) for(qw|rid priority hidden affiliate url version|); + return if !keys %set; + $self->dbExec('UPDATE affiliate_links !H WHERE id = ?', \%set, $id); +} + +sub dbAffiliateAdd { + my($self, %ops) = @_; + $self->dbExec('INSERT INTO affiliate_links (rid, priority, hidden, affiliate, url, version) VALUES(!l)', + [@ops{qw| rid priority hidden affiliate url version|}]); +} + + +1; + diff --git a/lib/VNDB/Handler/Affiliates.pm b/lib/VNDB/Handler/Affiliates.pm new file mode 100644 index 00000000..36435ade --- /dev/null +++ b/lib/VNDB/Handler/Affiliates.pm @@ -0,0 +1,123 @@ + +package VNDB::Handler::Affiliates; + +use strict; +use warnings; +use TUWF ':html'; +use VNDB::Func; + + +TUWF::register( + qr{affiliates} => \&list, + qr{affiliates/del/([1-9]\d*)} => \&del, + qr{affiliates/edit/([1-9]\d*)} => \&edit, + qr{affiliates/new} => \&edit, +); + + +sub list { + my $self = shift; + + return $self->htmlDenied if !$self->authCan('affiliate'); + my $f = $self->formValidate( + { get => 'a', required => 0, enum => [ 0..$#{$self->{affiliates}} ] } + ); + return $self->resNotFound if $f->{_err}; + + $self->htmlHeader(title => 'Affiliate administration interface'); + div class => 'mainbox'; + h1 'Affiliate administration interface'; + p class => 'browseopts'; + a defined($f->{a}) && $f->{a} == $_ ? (class => 'optselected') : (), href => "/affiliates?a=$_", $self->{affiliates}[$_]{name} + for (0..$#{$self->{affiliates}}); + end; + end; + + if(defined $f->{a}) { + my $list = $self->dbAffiliateGet(affiliate => $f->{a}, what => 'release'); + $self->htmlBrowse( + items => $list, + nextpage => 0, + options => {p=>0}, + pageurl => '', + header => [ ['Release'], ['Version'], ['Hid'], ['Prio'], ['URL'], ['Price'], [''] ], + row => sub { + my($s, $n, $l) = @_; + Tr $n % 2 ? (class => 'odd') : (); + td class => 'tc1'; a href => "/r$l->{rid}", shorten $l->{title}, 50; end; + td class => 'tc2', $l->{version} || ''; + td class => 'tc3', $l->{hidden} ? 'YES' : 'no'; + td class => 'tc4', $l->{priority}; + td class => 'tc5'; a href => $l->{url}, $l->{url}; end; + td class => 'tc6', sprintf '%s / %s', $l->{price}, $l->{lastfetch} ? $self->{l10n}->age($l->{lastfetch}) : '-'; + td class => 'tc7'; + a href => "/affiliates/edit/$l->{id}", 'edit'; + txt ' | '; + a href => "/affiliates/del/$l->{id}?formcode=".$self->authGetCode("/affiliates/del/$l->{id}"), 'del'; + end; + end; + }, + ); + } + $self->htmlFooter; +} + + +sub del { + my($self, $id) = @_; + return $self->htmlDenied if !$self->authCan('affiliate'); + return if !$self->authCheckCode; + my $l = $self->dbAffiliateGet(id => $id)->[0]; + return $self->resNotFound if !$l; + $self->dbAffiliateDel($id); + $self->resRedirect("/affiliates?a=$l->{affiliate}"); +} + + +sub edit { + my($self, $id) = @_; + return $self->htmlDenied if !$self->authCan('affiliate'); + + my $r = $id && $self->dbAffiliateGet(id => $id)->[0]; + return $self->resNotFound if $id && !$r; + + my $frm; + if($self->reqMethod eq 'POST') { + return if !$self->authCheckCode; + $frm = $self->formValidate( + { post => 'rid', required => 1, template => 'int' }, + { post => 'priority', required => 0, default => 0, template => 'int' }, + { post => 'hidden', required => 0, default => 0, enum => [0,1] }, + { post => 'affiliate',required => 1, enum => [0..$#{$self->{affiliates}}] }, + { post => 'url', required => 1 }, + { post => 'version', required => 0, default => '' }, + ); + if(!$frm->{_err}) { + $self->dbAffiliateEdit($id, %$frm) if $id; + $self->dbAffiliateAdd(%$frm) if !$id; + return $self->resRedirect("/affiliates?a=$frm->{affiliate}", 'post'); + } + } + + if($id) { + $frm->{$_} = $r->{$_} for(qw|rid priority hidden affiliate url version|); + } else { + $frm->{rid} = $self->reqGet('rid'); + } + + $self->htmlHeader(title => 'Edit affiliate link'); + $self->htmlForm({ frm => $frm, action => $id ? "/affiliates/edit/$id" : '/affiliates/new' }, 'blah' => [ 'Edit affiliate link', + [ input => short => 'rid', name => 'Release ID', width => 100 ], + [ input => short => 'priority', name => 'Priority', width => 50 ], + [ check => short => 'hidden', name => 'Hidden' ], + [ select => short => 'affiliate', name => 'Affiliate', options => [ map + [ $_, $self->{affiliates}[$_]{name} ], 0..$#{$self->{affiliates}} ] ], + [ input => short => 'url', name => 'URL', width => 400 ], + [ input => short => 'version', name => 'Version', width => 400 ], + ]); + $self->htmlFooter; +} + + +1; + diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index ff079675..0c9a6754 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -412,7 +412,7 @@ sub _affiliate_links { my $links = $self->dbAffiliateGet(rids => [ keys %r ]); return if !@$links; - $links = [ sort { $b->{priority} <=> $a->{priority} } @$links ]; + $links = [ sort { $b->{priority}||$self->{affiliates}[$b->{affiliate}]{default_prio} <=> $a->{priority}||$self->{affiliates}[$a->{affiliate}]{default_prio} } @$links ]; my $en = VNDB::L10N->get_handle('en'); Tr; td colspan => 2, id => 'buynow'; # don't call it "affiliate", most adblock filters have that included >_> @@ -489,6 +489,7 @@ sub _releases { } end; td class => 'tc6'; + a href => "/affiliates/new?rid=$rel->{id}", 'a' if $self->authCan('affiliate'); if($rel->{website}) { a href => $rel->{website}, rel => 'nofollow'; cssicon 'ext', mt '_vnpage_rel_extlink'; diff --git a/util/updates/update_2.20.sql b/util/updates/update_2.20.sql index 9ee38b07..51b9252b 100644 --- a/util/updates/update_2.20.sql +++ b/util/updates/update_2.20.sql @@ -41,3 +41,4 @@ CREATE INDEX affiliate_links_rid ON affiliate_links (rid) WHERE NOT hidden; --INSERT INTO affiliate_links (rid, priority, affiliate, url, version, lastfetch, price) VALUES -- (175, 1, 0, 'http://www.jbox.com/product/PCG4776', 'Original all-ages edition (Japanese)', NOW(), '$110.00'), -- (8124, 0, 0, 'http://www.jbox.com/product/PSPLB001', 'Converted edition (PSP, Japanese)', NOW(), '$78.00'); + -- cgit v1.2.3 From d1937fbfbc4996a524fe1649c081d9a486a34ab7 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sun, 10 Apr 2011 10:00:34 +0200 Subject: affiliates: Added support for URL modifying and default version string And updated the notes files. --- data/notes/sponsored-links | 24 +++++++++++------------- lib/VNDB/Handler/VNPage.pm | 11 +++++++---- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/data/notes/sponsored-links b/data/notes/sponsored-links index c31001d2..222553aa 100644 --- a/data/notes/sponsored-links +++ b/data/notes/sponsored-links @@ -1,7 +1,7 @@ Advertisements -Last modified: 2011-01 -Status: Long-term plans / nothing implemented yet +Last modified: 2011-04-10 +Status: Implemented / Implementation may differ from these notes Idea: (semi-)large "Buy now" / "Download now" button on VN pages, linking @@ -26,24 +26,18 @@ Possible parties interested in advertising: - Play-asia Has an affiliate system that includes direct links stores JAN, UPC, and catalog numbers -- Himeyashop / Erogeshop - Has no affiliate system but has shown interest in link exchanges in the past - Does not store JAN/UPC/catalog numbers - "Temporarily" closed, so probably not a good time to ask for ads? - DLSite English - Seems to have an affiliate system, haven't really looked at it yet + Has an affiliate system that includes direct links Most releases don't even have a JAN code or catalog number - MangaGamer Rather specific "shop", but could count as one. Has no affiliate system, but is planning to add one, as announced in http://mangagamer.wordpress.com/2010/12/31/holidays-passing/ Releases don't have catalog numbers or EAN codes -- Eroge-Europe.com - Seems to have an affiliate system, haven't really looked at it yet - Does not store JAN/UPC/catalog numbers - PaletWeb Has no affiliate system Does have JAN codes for a few titles, but inconsistent + Rather messy website... finding/updating links will be a chore - CDJapan Doesn't have that many VNs from what I've browsed, but still several Has an affiliate system (seems to include direct links) @@ -52,6 +46,13 @@ Possible parties interested in advertising: Does not seem to have many VNs (3 or 4?) Has no affiliate system Does not have JAN or catalog numbers +- Himeyashop / Erogeshop (out of business?) + Has no affiliate system but has shown interest in link exchanges in the past + Does not store JAN/UPC/catalog numbers + "Temporarily" closed, so probably not a good time to ask for ads? +- Eroge-Europe.com (out of business?) + Seems to have an affiliate system, haven't really looked at it yet + Does not store JAN/UPC/catalog numbers So who is going to update all those links? @@ -103,6 +104,3 @@ Three possibilities: special-case advertisers and give them special treatment or fetch additional information. -I would greatly prefer option #1, but since that's not very practical option -#3 (the VGMdb-like solution) is probably the best. - diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 0c9a6754..0fe71297 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -416,17 +416,20 @@ sub _affiliate_links { my $en = VNDB::L10N->get_handle('en'); Tr; td colspan => 2, id => 'buynow'; # don't call it "affiliate", most adblock filters have that included >_> - h1; a href => $links->[0]{url}, 'Buy now!'; end; + h1; a rel => 'nofollow', href => $self->{affiliates}[$links->[0]{affiliate}]{link_format} ? $self->{affiliates}[$links->[0]{affiliate}]{link_format}->($links->[0]{url}) : $links->[0]{url}, 'Buy now!'; end; ul; for my $link (@$links) { - li; a href => $link->{url}; + my $f = $self->{affiliates}[$link->{affiliate}]; + li; a rel => 'nofollow', href => $f->{link_format} ? $f->{link_format}->($link->{url}) : $link->{url}; use utf8; txt '→ '; - txt $link->{version} || join(', ', map $en->maketext("_lang_$_"), @{$r{$link->{rid}}{languages}}).' version'; + txt $link->{version} + || ($f->{default_version} && $f->{default_version}->($self, $link, $r{$link->{rid}})) + || join(', ', map $en->maketext("_lang_$_"), @{$r{$link->{rid}}{languages}}).' version'; txt ' '; acronym class => 'pricenote', title => sprintf('Last updated: %s.', $en->age($link->{lastfetch})), "for $link->{price}*" if $link->{price}; - txt " at $self->{affiliates}[$link->{affiliate}]{name}."; + txt " at $f->{name}."; end; end; } end; -- cgit v1.2.3 From 67afab5bfa32662f53699eb2fe37a9adec86a1ab Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 29 Apr 2011 12:11:28 +0200 Subject: affiliates: +data column, hide hidden links, better browser, Multi fixes --- data/script.js | 4 +++- lib/Multi/Core.pm | 2 +- lib/Multi/Maintenance.pm | 1 + lib/VNDB/DB/Affiliates.pm | 23 +++++++++++++++++++---- lib/VNDB/Handler/Affiliates.pm | 41 ++++++++++++++++++++++++++++++++--------- lib/VNDB/Handler/VNPage.pm | 2 +- util/sql/schema.sql | 3 ++- util/updates/update_2.20.sql | 7 ++----- 8 files changed, 61 insertions(+), 22 deletions(-) diff --git a/data/script.js b/data/script.js index a9e79aa1..41998405 100644 --- a/data/script.js +++ b/data/script.js @@ -2771,7 +2771,9 @@ if(byId('buynow')) { l[i].title = null; ddInit(l[i], 'bottom', function(acr) { return tag('p', {onmouseover:ddHide, style:'padding: 3px'}, - acr.buynow_last, tag('br', null), '* The displayed price only serves as an indication, actual price may differ.' + acr.buynow_last, tag('br', null), + '* The displayed price only serves as an indication and', + tag('br', null), 'usually excludes shipping. Actual price may differ.' ); }); } diff --git a/lib/Multi/Core.pm b/lib/Multi/Core.pm index 9eaa6269..3c9d8bae 100644 --- a/lib/Multi/Core.pm +++ b/lib/Multi/Core.pm @@ -98,7 +98,7 @@ sub log_msg { # msg sub log { # level, msg (my $p = eval { $_[SENDER][2]{$_[CALLER_STATE]}[0] } || '') =~ s/^Multi:://; log_msg sprintf '%s::%s: %s', $p, $_[CALLER_STATE], - $_[ARG1] ? sprintf($_[ARG0], @_[ARG1..$#_]) : $_[ARG0]; + $#_>ARG0 ? sprintf($_[ARG0], @_[ARG1..$#_]) : $_[ARG0]; } diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index fb0c336f..33154f9b 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -46,6 +46,7 @@ sub _start { sub shutdown { $_[KERNEL]->delay('daily'); $_[KERNEL]->delay('monthly'); + $_[KERNEL]->delay('vnsearch_check'); $_[KERNEL]->alias_remove('maintenance'); } diff --git a/lib/VNDB/DB/Affiliates.pm b/lib/VNDB/DB/Affiliates.pm index 2aa891ce..51320b47 100644 --- a/lib/VNDB/DB/Affiliates.pm +++ b/lib/VNDB/DB/Affiliates.pm @@ -9,23 +9,38 @@ use Exporter 'import'; our @EXPORT = qw|dbAffiliateGet dbAffiliateEdit dbAffiliateDel dbAffiliateAdd|; -# options: id rids affiliate hide_hidden +# options: id rids affiliate hidden sort reverse # what: release sub dbAffiliateGet { my($self, %o) = @_; + $o{sort} ||= 'id'; + $o{reverse} //= 0; my %where = ( $o{id} ? ('id = ?' => $o{id}) : (), $o{rids} ? ('rid IN(!l)' => [$o{rids}]) : (), defined($o{affiliate}) ? ('affiliate = ?' => $o{affiliate}) : (), - $o{hide_hidden} ? ('NOT hidden' => 1) : (), + defined($o{hidden}) ? ('!s af.hidden' => $o{hidden} ? '' : 'NOT') : (), ); my $join = $o{what} ? 'JOIN releases r ON r.id = af.rid JOIN releases_rev rr ON rr.id = r.latest' : ''; my $select = $o{what} ? ', rr.title' : ''; - return $self->dbAll("SELECT af.id, af.rid, af.hidden, af.priority, af.affiliate, af.url, af.version, extract('epoch' from af.lastfetch) as lastfetch, af.price$select - FROM affiliate_links af $join !W", \%where); + my $order = sprintf { + id => 'af.id %s', + rel => 'rr.title %s', + prio => 'af.priority %s', + url => 'af.url %s', + lastfetch => 'af.lastfetch %s', + }->{$o{sort}}, $o{reverse} ? 'DESC' : 'ASC'; + + return $self->dbAll(qq| + SELECT af.id, af.rid, af.hidden, af.priority, af.affiliate, af.url, af.version, + extract('epoch' from af.lastfetch) as lastfetch, af.price$select + FROM affiliate_links af + $join + !W + ORDER BY !s|, \%where, $order); } diff --git a/lib/VNDB/Handler/Affiliates.pm b/lib/VNDB/Handler/Affiliates.pm index 36435ade..e5e05d0f 100644 --- a/lib/VNDB/Handler/Affiliates.pm +++ b/lib/VNDB/Handler/Affiliates.pm @@ -20,7 +20,10 @@ sub list { return $self->htmlDenied if !$self->authCan('affiliate'); my $f = $self->formValidate( - { get => 'a', required => 0, enum => [ 0..$#{$self->{affiliates}} ] } + { get => 'a', required => 0, enum => [ 0..$#{$self->{affiliates}} ] }, + { get => 'h', required => 0, default => 0, enum => [ -1..1 ] }, + { get => 'o', required => 0, default => 'a', enum => ['a', 'd'] }, + { get => 's', required => 0, default => 'rel', enum => [qw|rel prio url lastfetch|] }, ); return $self->resNotFound if $f->{_err}; @@ -29,18 +32,37 @@ sub list { h1 'Affiliate administration interface'; p class => 'browseopts'; a defined($f->{a}) && $f->{a} == $_ ? (class => 'optselected') : (), href => "/affiliates?a=$_", $self->{affiliates}[$_]{name} - for (0..$#{$self->{affiliates}}); + for (grep $self->{affiliates}[$_], 0..$#{$self->{affiliates}}); end; + if(defined $f->{a}) { + p class => 'browseopts'; + a $f->{h} == -1 ? (class => 'optselected') : (), href => "/affiliates?a=$f->{a};h=-1",'all'; + a $f->{h} == 1 ? (class => 'optselected') : (), href => "/affiliates?a=$f->{a};h=1", 'hidden'; + a $f->{h} == 0 ? (class => 'optselected') : (), href => "/affiliates?a=$f->{a};h=0", 'non-hidden'; + end; + } end; if(defined $f->{a}) { - my $list = $self->dbAffiliateGet(affiliate => $f->{a}, what => 'release'); + my $list = $self->dbAffiliateGet( + affiliate => $f->{a}, hidden => $f->{h}==-1?undef:$f->{h}, + what => 'release', + sort => $f->{s}, reverse => $f->{o} eq 'd' + ); $self->htmlBrowse( items => $list, nextpage => 0, - options => {p=>0}, + options => {p=>0, %$f}, pageurl => '', - header => [ ['Release'], ['Version'], ['Hid'], ['Prio'], ['URL'], ['Price'], [''] ], + sorturl => "/affiliates?a=$f->{a}", + header => [ + ['Release', 'rel'], + ['Version'], + ['Hid'], + ['Prio', 'prio'], + ['Price / Lastfetch', 'lastfetch'], + ['', 'url' ] + ], row => sub { my($s, $n, $l) = @_; Tr $n % 2 ? (class => 'odd') : (); @@ -48,9 +70,10 @@ sub list { td class => 'tc2', $l->{version} || ''; td class => 'tc3', $l->{hidden} ? 'YES' : 'no'; td class => 'tc4', $l->{priority}; - td class => 'tc5'; a href => $l->{url}, $l->{url}; end; - td class => 'tc6', sprintf '%s / %s', $l->{price}, $l->{lastfetch} ? $self->{l10n}->age($l->{lastfetch}) : '-'; - td class => 'tc7'; + td class => 'tc5', sprintf '%s / %s', $l->{price}, $l->{lastfetch} ? $self->{l10n}->age($l->{lastfetch}) : '-'; + td class => 'tc6'; + a href => $l->{url}, 'link'; + txt ' | '; a href => "/affiliates/edit/$l->{id}", 'edit'; txt ' | '; a href => "/affiliates/del/$l->{id}?formcode=".$self->authGetCode("/affiliates/del/$l->{id}"), 'del'; @@ -111,7 +134,7 @@ sub edit { [ input => short => 'priority', name => 'Priority', width => 50 ], [ check => short => 'hidden', name => 'Hidden' ], [ select => short => 'affiliate', name => 'Affiliate', options => [ map - [ $_, $self->{affiliates}[$_]{name} ], 0..$#{$self->{affiliates}} ] ], + [ $_, $self->{affiliates}[$_]{name} ], grep $self->{affiliates}[$_], 0..$#{$self->{affiliates}} ] ], [ input => short => 'url', name => 'URL', width => 400 ], [ input => short => 'version', name => 'Version', width => 400 ], ]); diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 0fe71297..cd012aa2 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -409,7 +409,7 @@ sub _affiliate_links { my($self, $r) = @_; return if !keys @$r; my %r = map +($_->{id}, $_), @$r; - my $links = $self->dbAffiliateGet(rids => [ keys %r ]); + my $links = $self->dbAffiliateGet(rids => [ keys %r ], hidden => 0); return if !@$links; $links = [ sort { $b->{priority}||$self->{affiliates}[$b->{affiliate}]{default_prio} <=> $a->{priority}||$self->{affiliates}[$a->{affiliate}]{default_prio} } @$links ]; diff --git a/util/sql/schema.sql b/util/sql/schema.sql index d780bec8..0a593cec 100644 --- a/util/sql/schema.sql +++ b/util/sql/schema.sql @@ -10,7 +10,8 @@ CREATE TABLE affiliate_links ( url varchar NOT NULL, version varchar NOT NULL DEFAULT '', lastfetch timestamptz, - price varchar NOT NULL DEFAULT '' + price varchar NOT NULL DEFAULT '', + data varchar NOT NULL DEFAULT '' ); -- anime diff --git a/util/updates/update_2.20.sql b/util/updates/update_2.20.sql index 51b9252b..c4cdb880 100644 --- a/util/updates/update_2.20.sql +++ b/util/updates/update_2.20.sql @@ -33,12 +33,9 @@ CREATE TABLE affiliate_links ( url varchar NOT NULL, version varchar NOT NULL DEFAULT '', -- "x edition" or "x version", default used is " version" lastfetch timestamptz, -- last update of price - price varchar NOT NULL DEFAULT '' -- formatted, including currency, e.g. "$50" or "€34.95 / $50.46" + price varchar NOT NULL DEFAULT '', -- formatted, including currency, e.g. "$50" or "€34.95 / $50.46" + data varchar NOT NULL DEFAULT '' -- to be used by a fetch bot, if any ); CREATE INDEX affiliate_links_rid ON affiliate_links (rid) WHERE NOT hidden; ---INSERT INTO affiliate_links (rid, priority, affiliate, url, version, lastfetch, price) VALUES --- (175, 1, 0, 'http://www.jbox.com/product/PCG4776', 'Original all-ages edition (Japanese)', NOW(), '$110.00'), --- (8124, 0, 0, 'http://www.jbox.com/product/PSPLB001', 'Converted edition (PSP, Japanese)', NOW(), '$78.00'); - -- cgit v1.2.3 From 9b6da49f834d6f52604e460f14ca2cc690973f67 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 29 Apr 2011 12:17:28 +0200 Subject: Fixed CSS bug with doc paragraphs Bug introduced in 32489742a0b37fe908d3445b45a398b9f3232390 --- data/style.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/style.css b/data/style.css index c9af8eb7..094eb60c 100644 --- a/data/style.css +++ b/data/style.css @@ -184,8 +184,8 @@ div.mainbox, table.mainbox td { .mainbox h1 { color: $boxtitle$; font-size: 19px; margin: -5px 0 15px 0; } .mainbox h2.alttitle { color: $alttitle$; margin: -17px 0 15px 15px; font-weight: normal; } .mainbox p { margin: 3px 20px; } -.mainbox div div p, -.mainbox div table p { margin: 0; } +.mainbox div p, +.mainbox table p { margin: 0; } .mainbox h2 { font-weight: bold; font-size: 14px; margin: 10px 0 0 5px; } .mainbox.threelayout { border-collapse: separate; border-spacing: 10px; margin: 10px -10px -20px -10px; min-width: 100%; } -- cgit v1.2.3 From a3ff39b6269cb7114f0edee6a1f5fdb6dd163d40 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 30 Apr 2011 10:35:53 +0200 Subject: Bugfix: Don't allow unicode numbers as 'int' in formValidate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stuff like "168" went through earlier, but couldn't be interpreted by either perl or postgresql. --- ChangeLog | 1 + util/vndb.pl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 734689ab..a38b7316 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,7 @@ - Bugfix: Properly format future dates on my vn list - Bugfix: Properly position the sub-tabs on VN page without tags - Bugfix: Forgot to make two JS strings translatable + - Bugfix: Don't allow unicode numbers as 'int' in formValidate 2.19 - 2011-03-30 - Character database: diff --git a/util/vndb.pl b/util/vndb.pl index b6056dd4..765138fe 100755 --- a/util/vndb.pl +++ b/util/vndb.pl @@ -52,7 +52,7 @@ TUWF::set( mail => { regex => qr/^[^@<>]+@[^@.<>]+(?:\.[^@.<>]+)+$/ }, url => { regex => qr/^(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?$/ }, asciiprint => { regex => qr/^[\x20-\x7E]*$/ }, - int => { regex => qr/^-?\d+$/ }, + int => { regex => qr/^-?[0-9]+$/ }, pname => { regex => qr/^[a-z0-9-]*$/ }, }, ); -- cgit v1.2.3 From 0dbd4d544d54efecb01d5359a5db69548b5513c0 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 30 Apr 2011 11:01:04 +0200 Subject: Added "Add character" link to VN pages --- ChangeLog | 1 + data/lang.txt | 7 +++++++ data/style.css | 2 +- lib/VNDB/Handler/Chars.pm | 4 ++++ lib/VNDB/Handler/VNPage.pm | 6 +++++- 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index a38b7316..170a8e9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ - Added char/tag/trait stats to database statistics box - Update traits_chars cache daily using Multi::Maintenance - Toggle [spoiler] tag visibility with global setting rather than mouse-over + - Added "Add character" link to VN pages - Cleaned up CSS code - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser diff --git a/data/lang.txt b/data/lang.txt index b4951352..7faca7c0 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -8371,6 +8371,13 @@ cs : K této vizuální novele zatím nemáme informace o žádném vydání... hu : Még nincs információnk ennek a visual novelnek a kiadásairól... nl : We hebben op dit moment nog geen informatie over uitgaven van deze visual novel... +:_vnpage_char_add +en : add character +ru*: +cs*: +hu*: +nl : voeg karakter toe + :_vnpage_rel_add en : add release ru : добавить выпуск diff --git a/data/style.css b/data/style.css index 094eb60c..9ed059c3 100644 --- a/data/style.css +++ b/data/style.css @@ -187,6 +187,7 @@ div.mainbox, table.mainbox td { .mainbox div p, .mainbox table p { margin: 0; } .mainbox h2 { font-weight: bold; font-size: 14px; margin: 10px 0 0 5px; } +a.addnew, p.addnew { float: right; margin: 0 } .mainbox.threelayout { border-collapse: separate; border-spacing: 10px; margin: 10px -10px -20px -10px; min-width: 100%; } .mainbox.threelayout td { width: 32%; padding: 0 2px 10px 2px; } @@ -365,7 +366,6 @@ div#vntags { margin: 15px 30px 0 30px; border-top: 1px solid .releases td.tc5 { width: 70px; } .releases td.tc5 a { color: $maintext$; border: 0; } .releases td.tc6 { text-align: right; width: 25px; padding: 0; } -a.addnew { float: right; } #screenshots p.rel { background: url($_boxbg$) repeat; diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm index 9308cecf..347acb08 100644 --- a/lib/VNDB/Handler/Chars.pm +++ b/lib/VNDB/Handler/Chars.pm @@ -335,6 +335,10 @@ sub edit { } } + if(!$id) { + my $vid = $self->formValidate({ get => 'vid', required => 1, template => 'int'}); + $frm->{vns} //= "$vid->{vid}-0-0-primary" if !$vid->{_err}; + } $frm->{$_} //= $b4{$_} for keys %b4; $frm->{editsum} //= sprintf 'Reverted to revision c%d.%d', $id, $rev if !$copy && $rev; $frm->{editsum} = sprintf 'New character based on c%d.%d', $id, $r->{rev} if $copy; diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index cd012aa2..42f1343a 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -441,7 +441,11 @@ sub _releases { my($self, $v, $r) = @_; div class => 'mainbox releases'; - a class => 'addnew', href => "/v$v->{id}/add", mt '_vnpage_rel_add'; + p class => 'addnew'; + a href => "/c/new?vid=$v->{id}", mt '_vnpage_char_add'; + txt ' | '; + a href => "/v$v->{id}/add", mt '_vnpage_rel_add'; + end; h1 mt '_vnpage_rel'; if(!@$r) { p mt '_vnpage_rel_none'; -- cgit v1.2.3 From 53d155d44e60c2fa56a5d8a9ab861454eb655a5e Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 30 Apr 2011 11:19:48 +0200 Subject: Added "Image ID" field to VN image uploader --- ChangeLog | 1 + data/lang.txt | 14 +++++++++++ lib/VNDB/Handler/VNEdit.pm | 62 +++++++++++++++++++++++----------------------- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index 170a8e9f..de66850e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ - Update traits_chars cache daily using Multi::Maintenance - Toggle [spoiler] tag visibility with global setting rather than mouse-over - Added "Add character" link to VN pages + - Added "Image ID" field to VN image uploader - Cleaned up CSS code - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser diff --git a/data/lang.txt b/data/lang.txt index 7faca7c0..6debbde3 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -7497,6 +7497,20 @@ cs : ~[obrázek se zpracovává, vraťte se prosím za několik minut~] hu : ~[a kép feldolgozás alatt van, gyere vissza pár perc múlva~] nl : ~[bezig met het verwerken van het plaatje, kom a.u.b. terug in een paar minuten~] +:_vnedit_image_id +en : Image ID +ru*: +cs*: ID obrázku +hu*: Kép ID (azonosító) +nl : Plaatje ID + +:_vnedit_image_id_msg +en : Use a character image that is already on the server. Set to '0' to remove the current image. +ru*: +cs*: +hu*: Használj egy olyan képet ami már megtalálható a szerveren. Ha '0'-ra állítod törölheted a jelenlegi képet. +nl : Gebruik een karakterplaatje dat al op de server staat. Gebruik '0' om een huidig plaatje te verwijderen. + :_vnedit_image_upload en : Upload new image ru : Загрузить новое изображение diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index ce564fc0..8657a6f6 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -28,7 +28,7 @@ sub edit { my $r = $v ? $self->dbReleaseGet(vid => $v->{id}) : []; my %b4 = !$vid ? () : ( - (map { $_ => $v->{$_} } qw|title original desc alias length l_wp l_encubed l_renai l_vnn img_nsfw ihid ilock|), + (map { $_ => $v->{$_} } qw|title original desc alias length l_wp l_encubed l_renai l_vnn image img_nsfw ihid ilock|), anime => join(' ', sort { $a <=> $b } map $_->{id}, @{$v->{anime}}), vnrelations => join('|||', map $_->{relation}.','.$_->{id}.','.($_->{official}?1:0).','.$_->{title}, sort { $a->{id} <=> $b->{id} } @{$v->{relations}}), screenshots => join(' ', map sprintf('%d,%d,%d', $_->{id}, $_->{nsfw}?1:0, $_->{rid}), @{$v->{screenshots}}), @@ -48,7 +48,7 @@ sub edit { { post => 'l_renai', required => 0, default => '', maxlength => 100 }, { post => 'l_vnn', required => 0, default => $b4{l_vnn}||0, template => 'int' }, { post => 'anime', required => 0, default => '' }, - { post => 'previmage', required => 0, default => 0, template => 'int' }, + { post => 'image', required => 0, default => 0, template => 'int' }, { post => 'img_nsfw', required => 0, default => 0 }, { post => 'vnrelations', required => 0, default => '', maxlength => 5000 }, { post => 'screenshots', required => 0, default => '', maxlength => 1000 }, @@ -60,7 +60,7 @@ sub edit { push @{$frm->{_err}}, 'badeditsum' if !$frm->{editsum} || lc($frm->{editsum}) eq lc($frm->{desc}); # handle image upload - my $image = _uploadimage($self, $v, $frm); + $frm->{image} = _uploadimage($self, $v, $frm); if(!$frm->{_err}) { # parse and re-sort fields that have multiple representations of the same information @@ -86,15 +86,13 @@ sub edit { # nothing changed? just redirect return $self->resRedirect("/v$vid", 'post') - if $vid && !$self->reqPost('img') && $image == $v->{image} - && !grep $frm->{$_} ne $b4{$_}, keys %b4; + if $vid && !grep $frm->{$_} ne $b4{$_}, keys %b4; # perform the edit/add my $nrev = $self->dbItemEdit(v => $vid ? $v->{cid} : undef, - (map { $_ => $frm->{$_} } qw|title original alias desc length l_wp l_encubed l_renai l_vnn editsum img_nsfw ihid ilock|), + (map { $_ => $frm->{$_} } qw|title original image alias desc length l_wp l_encubed l_renai l_vnn editsum img_nsfw ihid ilock|), anime => [ keys %$anime ], relations => $relations, - image => $image, screenshots => $screenshots, ); @@ -123,7 +121,7 @@ sub edit { sub _uploadimage { my($self, $v, $frm) = @_; - return $v ? $frm->{previmage} : 0 if $frm->{_err} || !$self->reqPost('img'); + return $v ? $frm->{image} : 0 if $frm->{_err} || !$self->reqPost('img'); # perform some elementary checks my $imgdata = $self->reqUploadRaw('img'); @@ -163,29 +161,31 @@ sub _form { [ static => content => mt '_vnedit_anime_msg' ], ], - vn_img => [ mt('_vnedit_image'), - [ hidden => short => 'previmage', value => $v ? $v->{image} : 0 ], - [ static => nolabel => 1, content => sub { - div class => 'img'; - p mt '_vnedit_image_none' if !$v || !$v->{image}; - p mt '_vnedit_image_processing' if $v && $v->{image} < 0; - img src => sprintf("%s/cv/%02d/%d.jpg", $self->{url_static}, $v->{image}%100, $v->{image}), alt => $v->{title} if $v && $v->{image} > 0; - end; - div; - - h2 mt '_vnedit_image_upload'; - input type => 'file', class => 'text', name => 'img', id => 'img'; - p mt('_vnedit_image_upload_msg'); - br; br; br; - - h2 mt '_vnedit_image_nsfw'; - input type => 'checkbox', class => 'checkbox', id => 'img_nsfw', name => 'img_nsfw', - $frm->{img_nsfw} ? (checked => 'checked') : (); - label class => 'checkbox', for => 'img_nsfw', mt '_vnedit_image_nsfw_check'; - p mt '_vnedit_image_nsfw_msg'; - end 'div'; - }], - ], + vn_img => [ mt('_vnedit_image'), [ static => nolabel => 1, content => sub { + div class => 'img'; + p mt '_vnedit_image_none' if !$v || !$v->{image}; + p mt '_vnedit_image_processing' if $v && $v->{image} < 0; + img src => sprintf("%s/cv/%02d/%d.jpg", $self->{url_static}, $v->{image}%100, $v->{image}), alt => $v->{title} if $v && $v->{image} > 0; + end; + + div; + h2 mt '_vnedit_image_id'; + input type => 'text', class => 'text', name => 'image', id => 'image', value => $frm->{image}||''; + p mt '_vnedit_image_id_msg'; + br; br; + + h2 mt '_vnedit_image_upload'; + input type => 'file', class => 'text', name => 'img', id => 'img'; + p mt('_vnedit_image_upload_msg'); + br; br; br; + + h2 mt '_vnedit_image_nsfw'; + input type => 'checkbox', class => 'checkbox', id => 'img_nsfw', name => 'img_nsfw', + $frm->{img_nsfw} ? (checked => 'checked') : (); + label class => 'checkbox', for => 'img_nsfw', mt '_vnedit_image_nsfw_check'; + p mt '_vnedit_image_nsfw_msg'; + end 'div'; + }]], vn_rel => [ mt('_vnedit_rel'), [ hidden => short => 'vnrelations' ], -- cgit v1.2.3 From 28cf4e0e79487d82a325238105f670713b20bf85 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 30 Apr 2011 16:22:28 +0200 Subject: affiliates: Improved default version info --- lib/VNDB/Handler/Affiliates.pm | 2 +- lib/VNDB/Handler/VNPage.pm | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/VNDB/Handler/Affiliates.pm b/lib/VNDB/Handler/Affiliates.pm index e5e05d0f..ac46c68d 100644 --- a/lib/VNDB/Handler/Affiliates.pm +++ b/lib/VNDB/Handler/Affiliates.pm @@ -54,7 +54,7 @@ sub list { nextpage => 0, options => {p=>0, %$f}, pageurl => '', - sorturl => "/affiliates?a=$f->{a}", + sorturl => "/affiliates?a=$f->{a};h=$f->{h}", header => [ ['Release', 'rel'], ['Version'], diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 42f1343a..44a63db8 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -420,12 +420,17 @@ sub _affiliate_links { ul; for my $link (@$links) { my $f = $self->{affiliates}[$link->{affiliate}]; + + my $rel = $r{$link->{rid}}; + my $plat = grep($_ eq 'win', @{$rel->{platforms}}) ? '' : ' '.join(' and ', map $en->maketext("_plat_$_"), @{$rel->{platforms}}); + my $version = join(', ', map $en->maketext("_lang_$_"), @{$rel->{languages}}).$plat.' version'; + li; a rel => 'nofollow', href => $f->{link_format} ? $f->{link_format}->($link->{url}) : $link->{url}; use utf8; txt '→ '; txt $link->{version} - || ($f->{default_version} && $f->{default_version}->($self, $link, $r{$link->{rid}})) - || join(', ', map $en->maketext("_lang_$_"), @{$r{$link->{rid}}{languages}}).' version'; + || ($f->{default_version} && $f->{default_version}->($self, $link, $rel)) + || $version; txt ' '; acronym class => 'pricenote', title => sprintf('Last updated: %s.', $en->age($link->{lastfetch})), "for $link->{price}*" if $link->{price}; -- cgit v1.2.3 From 76b970a49e1d6374a3ec351debcf846ee00b78c0 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 30 Apr 2011 16:28:49 +0200 Subject: Added "All except characters" filter to history browser --- ChangeLog | 1 + data/lang.txt | 7 +++++++ lib/VNDB/DB/Misc.pm | 3 ++- lib/VNDB/Handler/Misc.pm | 5 +++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index de66850e..d2b98f30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ - Toggle [spoiler] tag visibility with global setting rather than mouse-over - Added "Add character" link to VN pages - Added "Image ID" field to VN image uploader + - Added "All except characters" filter to history browser - Cleaned up CSS code - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser diff --git a/data/lang.txt b/data/lang.txt index 6debbde3..b63cc3e4 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -2520,6 +2520,13 @@ cs : Pouze postavy hu : Csak szereplők nl : Alleen karakters +:_hist_filter_nochars +en : All except characters +ru*: +cs*: +hu*: +nl : Alles behalve karakters + :_hist_filter_allactions en : Show all changes ru : Показать все изменения diff --git a/lib/VNDB/DB/Misc.pm b/lib/VNDB/DB/Misc.pm index 2f98abe2..3155ca56 100644 --- a/lib/VNDB/DB/Misc.pm +++ b/lib/VNDB/DB/Misc.pm @@ -64,6 +64,7 @@ sub dbRevisionGet { # what types should we join? my @types = ( !$o{type} ? ('v', 'r', 'p', 'c') : + ref($o{type}) ? @{$o{type}} : $o{type} ne 'v' ? $o{type} : $o{releases} ? ('v', 'r') : 'v' ); @@ -73,7 +74,7 @@ sub dbRevisionGet { q{((h.type = 'v' AND vr.vid = ?) OR (h.type = 'r' AND h.id = ANY(ARRAY(SELECT rv.rid FROM releases_vn rv WHERE rv.vid = ?))))} => [$o{iid}, $o{iid}], ) : ( $o{type} ? ( - 'h.type = ?' => $o{type} ) : (), + 'h.type IN(!l)' => [ ref($o{type})?$o{type}:[$o{type}] ] ) : (), $o{iid} ? ( '!sr.!sid = ?' => [ $o{type}, $o{type}, $o{iid} ] ) : (), ), diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm index 8f5b4949..167cc152 100644 --- a/lib/VNDB/Handler/Misc.pm +++ b/lib/VNDB/Handler/Misc.pm @@ -196,7 +196,7 @@ sub history { { get => 'p', required => 0, default => 1, template => 'int' }, { get => 'm', required => 0, default => !$type, enum => [ 0, 1 ] }, { get => 'h', required => 0, default => 0, enum => [ -1..1 ] }, - { get => 't', required => 0, default => '', enum => [qw|v r p c|] }, + { get => 't', required => 0, default => '', enum => [qw|v r p c a|] }, { get => 'e', required => 0, default => 0, enum => [ -1..1 ] }, { get => 'r', required => 0, default => 0, enum => [ 0, 1 ] }, ); @@ -216,7 +216,7 @@ sub history { what => 'item user', $type && $type ne 'u' ? ( type => $type, iid => $id ) : (), $type eq 'u' ? ( uid => $id ) : (), - $f->{t} ? ( type => $f->{t} ) : (), + $f->{t} ? ( type => $f->{t} eq 'a' ? [qw|v r p|] : $f->{t} ) : (), page => $f->{p}, results => 50, auto => $f->{m}, @@ -262,6 +262,7 @@ sub history { a $f->{t} eq 'r' ? (class => 'optselected') : (), href => $u->(t => 'r'), mt '_hist_filter_onlyreleases'; a $f->{t} eq 'p' ? (class => 'optselected') : (), href => $u->(t => 'p'), mt '_hist_filter_onlyproducers'; a $f->{t} eq 'c' ? (class => 'optselected') : (), href => $u->(t => 'c'), mt '_hist_filter_onlychars'; + a $f->{t} eq 'a' ? (class => 'optselected') : (), href => $u->(t => 'a'), mt '_hist_filter_nochars'; end; p class => 'browseopts'; a !$f->{e} ? (class => 'optselected') : (), href => $u->(e => 0), mt '_hist_filter_allactions'; -- cgit v1.2.3 From 57b464e826e5f24828dec9401b70baaa43410b6c Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 30 Apr 2011 16:50:28 +0200 Subject: Cleaned up permissions - Removed 'hist' and 'mod', weren't used at all - Merged 'del' and 'lock' into a single 'dbmod' --- ChangeLog | 1 + data/global.pl | 14 +++++++------- lib/VNDB/Handler/Affiliates.pm | 4 ++-- lib/VNDB/Handler/Chars.pm | 2 +- lib/VNDB/Handler/Misc.pm | 2 +- lib/VNDB/Handler/Producers.pm | 2 +- lib/VNDB/Handler/Releases.pm | 2 +- lib/VNDB/Handler/VNEdit.pm | 2 +- lib/VNDB/Util/CommonHTML.pm | 6 +++--- lib/VNDB/Util/FormHTML.pm | 6 +----- 10 files changed, 19 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index d2b98f30..210880bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ - Added "Image ID" field to VN image uploader - Added "All except characters" filter to history browser - Cleaned up CSS code + - Cleaned up permissions - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser - Bugfix: properly announce chars and traits in Multi::IRC diff --git a/data/global.pl b/data/global.pl index c985b8ea..d19056f7 100644 --- a/data/global.pl +++ b/data/global.pl @@ -32,13 +32,13 @@ our %S = (%S, ch_size => [ 256, 300 ], # max. w*h of char images cv_size => [ 256, 400 ], # max. w*h of cover images user_ranks => [ - # allowed actions # DB number - [qw| hist |], # 0 - [qw| hist |], # 1 - [qw| hist board |], # 2 - [qw| hist board edit tag |], # 3 - [qw| hist board boardmod edit charedit tag mod lock del tagmod |], # 4 - [qw| hist board boardmod edit charedit tag mod lock del tagmod usermod affiliate |], # 5 + # allowed actions # DB number + [qw| |], # 0 + [qw| |], # 1 + [qw| board |], # 2 + [qw| board edit tag |], # 3 + [qw| board boardmod edit charedit tag dbmod tagmod |], # 4 + [qw| board boardmod edit charedit tag dbmod tagmod usermod affiliate |], # 5 ], languages => [qw|cs da de en es fi fr hu it ja ko nl no pl pt-br pt-pt ru sk sv tr vi zh|], producer_types => [qw|co in ng|], diff --git a/lib/VNDB/Handler/Affiliates.pm b/lib/VNDB/Handler/Affiliates.pm index ac46c68d..679d6ee2 100644 --- a/lib/VNDB/Handler/Affiliates.pm +++ b/lib/VNDB/Handler/Affiliates.pm @@ -9,7 +9,7 @@ use VNDB::Func; TUWF::register( qr{affiliates} => \&list, - qr{affiliates/del/([1-9]\d*)} => \&del, + qr{affiliates/del/([1-9]\d*)} => \&linkdel, qr{affiliates/edit/([1-9]\d*)} => \&edit, qr{affiliates/new} => \&edit, ); @@ -86,7 +86,7 @@ sub list { } -sub del { +sub linkdel { my($self, $id) = @_; return $self->htmlDenied if !$self->authCan('affiliate'); return if !$self->authCheckCode; diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm index 347acb08..8edb6236 100644 --- a/lib/VNDB/Handler/Chars.pm +++ b/lib/VNDB/Handler/Chars.pm @@ -257,7 +257,7 @@ sub edit { $rev = undef if !$r || $r->{cid} == $r->{latest}; return $self->htmlDenied if !$self->authCan('charedit') - || $id && ($r->{locked} && !$self->authCan('lock') || $r->{hidden} && !$self->authCan('del')); + || $id && (($r->{locked} || $r->{hidden}) && !$self->authCan('dbmod')); my %b4 = !$id ? () : ( (map +($_ => $r->{$_}), qw|name original alias desc image ihid ilock s_bust s_waist s_hip height weight bloodt gender main_spoil|), diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm index 167cc152..643af1cf 100644 --- a/lib/VNDB/Handler/Misc.pm +++ b/lib/VNDB/Handler/Misc.pm @@ -250,7 +250,7 @@ sub history { end; } if(!$type || $type eq 'u') { - if($self->authCan('del')) { + if($self->authCan('dbmod')) { p class => 'browseopts'; a $f->{h} == 1 ? (class => 'optselected') : (), href => $u->(h => 1), mt '_hist_filter_hidedel'; a $f->{h} == -1 ? (class => 'optselected') : (), href => $u->(h => -1), mt '_hist_filter_showdel'; diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index 5030c1a3..52db6edf 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -205,7 +205,7 @@ sub edit { $rev = undef if !$p || $p->{cid} == $p->{latest}; return $self->htmlDenied if !$self->authCan('edit') - || $pid && ($p->{locked} && !$self->authCan('lock') || $p->{hidden} && !$self->authCan('del')); + || $pid && (($p->{locked} || $p->{hidden}) && !$self->authCan('dbmod')); my %b4 = !$pid ? () : ( (map { $_ => $p->{$_} } qw|type name original lang website desc alias ihid ilock|), diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index 159b7c3f..dd2b278e 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -280,7 +280,7 @@ sub edit { return $self->resNotFound if $vid && !$v->{id}; return $self->htmlDenied if !$self->authCan('edit') - || $rid && ($r->{locked} && !$self->authCan('lock') || $r->{hidden} && !$self->authCan('del')); + || $rid && (($r->{locked} || $r->{hidden}) && !$self->authCan('dbmod')); my $vn = $rid ? $r->{vn} : [{ vid => $vid, title => $v->{title} }]; my %b4 = !$rid ? () : ( diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index 8657a6f6..d0848c09 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -23,7 +23,7 @@ sub edit { $rev = undef if !$vid || $v->{cid} == $v->{latest}; return $self->htmlDenied if !$self->authCan('edit') - || $vid && ($v->{locked} && !$self->authCan('lock') || $v->{hidden} && !$self->authCan('del')); + || $vid && (($v->{locked} || $v->{hidden}) && !$self->authCan('dbmod')); my $r = $v ? $self->dbReleaseGet(vid => $v->{id}) : []; diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index e1765d0d..5f2fb330 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -72,8 +72,8 @@ sub htmlMainTabs { } if( $type eq 'u' && ($self->authInfo->{id} && $obj->{id} == $self->authInfo->{id} || $self->authCan('usermod')) - || $type =~ /[vrp]/ && $self->authCan('edit') && (!$obj->{locked} || $self->authCan('lock')) && (!$obj->{hidden} || $self->authCan('del')) - || $type eq 'c' && $self->authCan('charedit') && (!$obj->{locked} || $self->authCan('lock')) && (!$obj->{hidden} || $self->authCan('del')) + || $type =~ /[vrp]/ && $self->authCan('edit') && ((!$obj->{locked} && !$obj->{hidden}) || $self->authCan('dbmod')) + || $type eq 'c' && $self->authCan('charedit') && ((!$obj->{locked} && !$obj->{hidden}) || $self->authCan('dbmod')) || $type =~ /[gi]/ && $self->authCan('tagmod') ) { li $sel eq 'edit' ? (class => 'tabselected') : (); @@ -143,7 +143,7 @@ sub htmlHiddenMessage { end; end; end 'div'; - return $self->htmlFooter() || 1 if !$self->authCan('del'); + return $self->htmlFooter() || 1 if !$self->authCan('dbmod'); return 0; } diff --git a/lib/VNDB/Util/FormHTML.pm b/lib/VNDB/Util/FormHTML.pm index 68b6a101..805467f6 100644 --- a/lib/VNDB/Util/FormHTML.pm +++ b/lib/VNDB/Util/FormHTML.pm @@ -214,15 +214,11 @@ sub htmlForm { fieldset class => 'submit'; if($options->{editsum}) { # hidden / locked checkbox - if($self->authCan('del')) { + if($self->authCan('dbmod')) { input type => 'checkbox', name => 'ihid', id => 'ihid', value => 1, $options->{frm}{ihid} ? (checked => 'checked') : (); label for => 'ihid', mt '_form_ihid'; - } - if($self->authCan('lock')) { input type => 'checkbox', name => 'ilock', id => 'ilock', value => 1, $options->{frm}{ilock} ? (checked => 'checked') : (); label for => 'ilock', mt '_form_ilock'; - } - if($self->authCan('lock') || $self->authCan('del')) { br; txt mt('_form_hidlock_note'); br; } -- cgit v1.2.3 From 4873e8583189ee9c611fadd27d491dc104c52b57 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sat, 30 Apr 2011 18:04:50 +0200 Subject: Replaced user ranks with a permission system This is far more flexible. --- ChangeLog | 1 + data/global.pl | 12 ++-------- data/lang.txt | 57 +++++--------------------------------------- lib/VNDB/DB/Users.pm | 4 ++-- lib/VNDB/Handler/Users.pm | 16 ++++++++----- lib/VNDB/Util/Auth.pm | 5 ++-- lib/VNDB/Util/LayoutHTML.pm | 1 - util/sql/schema.sql | 2 +- util/updates/update_2.20.sql | 13 ++++++++++ 9 files changed, 37 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index 210880bf..4a362661 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ - Added "All except characters" filter to history browser - Cleaned up CSS code - Cleaned up permissions + - Replaced user ranks with a permission system - Bugfix: don't accidentally remove char traits when editing - Bugfix: fixed possible SQL table name clash on history browser - Bugfix: properly announce chars and traits in Multi::IRC diff --git a/data/global.pl b/data/global.pl index d19056f7..2453ed6b 100644 --- a/data/global.pl +++ b/data/global.pl @@ -31,15 +31,8 @@ our %S = (%S, scr_size => [ 136, 102 ], # w*h of screenshot thumbnails ch_size => [ 256, 300 ], # max. w*h of char images cv_size => [ 256, 400 ], # max. w*h of cover images - user_ranks => [ - # allowed actions # DB number - [qw| |], # 0 - [qw| |], # 1 - [qw| board |], # 2 - [qw| board edit tag |], # 3 - [qw| board boardmod edit charedit tag dbmod tagmod |], # 4 - [qw| board boardmod edit charedit tag dbmod tagmod usermod affiliate |], # 5 - ], + # bit flags + permissions => {qw| board 1 boardmod 2 edit 4 charedit 8 tag 16 dbmod 32 tagmod 64 usermod 128 affiliate 256 |}, languages => [qw|cs da de en es fi fr hu it ja ko nl no pl pt-br pt-pt ru sk sv tr vi zh|], producer_types => [qw|co in ng|], discussion_boards => [qw|an db ge v p u|], # <- note that some properties of these boards are hard-coded @@ -137,4 +130,3 @@ require $ROOT.'/data/config.pl' if -f $ROOT.'/data/config.pl'; 1; - diff --git a/data/lang.txt b/data/lang.txt index b63cc3e4..f3171116 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -104,51 +104,6 @@ ends with ']'. The following options are supported: # data/global.pl - used in many places -# user ranks - -:_urank_0 -en : visitor -ru : посетитель -cs : návštěvník -hu : vendég -nl : bezoeker - -:_urank_1 -en : banned -ru : забанен -cs : zabanovaný -hu : kicsapva -nl : gebanned - -:_urank_2 -en : loser -ru : лузер -cs : loser -hu : vesztes -nl : sukkel - -:_urank_3 -en : user -ru : пользователь -cs : uživatel -hu : felhasználó -nl : gebruiker - -:_urank_4 -en : mod -ru : модератор -cs : moderátor -hu : mod -nl : - -:_urank_5 -en : admin -ru : администратор -cs : administrátor -hu : admin -nl : - - # languages :_lang_cs @@ -6749,12 +6704,12 @@ cs : Uživatelské jméno hu : Felhasználónév nl : Gebruikersnaam -:_usere_rank -en : Rank -ru : Ранг -cs : Postavení -hu : Rang -nl : +:_usere_perm +en : Permissions +ru*: +cs*: +hu*: +nl : Permissies :_usere_ignvotes en : Ignore votes in VN statistics diff --git a/lib/VNDB/DB/Users.pm b/lib/VNDB/DB/Users.pm index 17f360cc..abea9bec 100644 --- a/lib/VNDB/DB/Users.pm +++ b/lib/VNDB/DB/Users.pm @@ -55,7 +55,7 @@ sub dbUserGet { qw|id username c_votes c_changes c_tags|, q|extract('epoch' from registered) as registered|, $o{what} =~ /extended/ ? ( - qw|mail rank salt ign_votes|, + qw|mail perm salt ign_votes|, q|encode(passwd, 'hex') AS passwd| ) : (), $o{what} =~ /hide_list/ ? 'up.value AS hide_list' : (), @@ -118,7 +118,7 @@ sub dbUserEdit { my %h; defined $o{$_} && ($h{$_.' = ?'} = $o{$_}) - for (qw| username mail rank salt ign_votes |); + for (qw| username mail perm salt ign_votes |); $h{'passwd = decode(?, \'hex\')'} = $o{passwd} if defined $o{passwd}; diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index 6cedc734..dc748f75 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -301,7 +301,7 @@ sub edit { $frm = $self->formValidate( $self->authCan('usermod') ? ( { post => 'usrname', template => 'pname', minlength => 2, maxlength => 15 }, - { post => 'rank', enum => [ 1..$#{$self->{user_ranks}} ] }, + { post => 'perms', required => 0, multi => 1, enum => [ keys %{$self->{permissions}} ] }, { post => 'ign_votes', required => 0, default => 0 }, ) : (), { post => 'mail', template => 'mail' }, @@ -318,7 +318,10 @@ sub edit { $self->dbUserPrefSet($uid, $_ => $frm->{$_}) for (qw|skin customcss show_nsfw hide_list |); my %o; $o{username} = $frm->{usrname} if $frm->{usrname}; - $o{rank} = $frm->{rank} if $frm->{rank}; + if($self->authCan('usermod')) { + $o{perm} = 0; + $o{perm} += $self->{permissions}{$_} for(@{ delete $frm->{perms} }); + } $o{mail} = $frm->{mail}; ($o{passwd}, $o{salt}) = $self->authPreparePass($frm->{usrpass}) if $frm->{usrpass}; $o{ign_votes} = $frm->{ign_votes} ? 1 : 0 if $self->authCan('usermod'); @@ -330,8 +333,9 @@ sub edit { } # fill out default values - $frm->{usrname} ||= $u->{username}; - $frm->{$_} ||= $u->{$_} for(qw|rank mail|); + $frm->{usrname} ||= $u->{username}; + $frm->{mail} ||= $u->{mail}; + $frm->{perms} ||= [ grep $u->{perm} & $self->{permissions}{$_}, keys %{$self->{permissions}} ]; $frm->{$_} //= $u->{prefs}{$_} for(qw|skin customcss show_nsfw hide_list|); $frm->{ign_votes} = $u->{ign_votes} if !defined $frm->{ign_votes}; @@ -350,8 +354,8 @@ sub edit { [ part => title => mt '_usere_geninfo' ], $self->authCan('usermod') ? ( [ input => short => 'usrname', name => mt('_usere_username') ], - [ select => short => 'rank', name => mt('_usere_rank'), options => [ - map [ $_, mt '_urank_'.$_ ], 1..$#{$self->{user_ranks}} ] ], + [ select => short => 'perms', name => mt('_usere_perm'), multi => 1, size => (scalar keys %{$self->{permissions}}), options => [ + map [ $_, $_ ], sort keys %{$self->{permissions}} ] ], [ check => short => 'ign_votes', name => mt '_usere_ignvotes' ], ) : ( [ static => label => mt('_usere_username'), content => $frm->{usrname} ], diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm index 88e68edc..89807bef 100644 --- a/lib/VNDB/Util/Auth.pm +++ b/lib/VNDB/Util/Auth.pm @@ -88,8 +88,7 @@ sub authInfo { # a certain action. Argument is the action name as defined in global.pl sub authCan { my($self, $act) = @_; - my $r = $self->{_auth} ? $self->{_auth}{rank} : 0; - return scalar grep $_ eq $act, @{$self->{user_ranks}[$r]}[0..$#{$self->{user_ranks}[$r]}]; + return $self->{_auth} ? $self->{_auth}{perm} & $self->{permissions}{$act} : 0; } @@ -102,7 +101,7 @@ sub _authCheck { return 0 if !$user || length($user) > 15 || length($user) < 2 || !$pass; my $d = $self->dbUserGet(username => $user, what => 'extended notifycount')->[0]; - return 0 if !defined $d->{id} || !$d->{rank}; + return 0 if !$d->{id}; if(_authEncryptPass($self, $pass, $d->{salt}) eq $d->{passwd}) { $self->{_auth} = $d; diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index 5dd8038f..e1e21924 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -89,7 +89,6 @@ sub _menu { my $nc = $self->authInfo->{notifycount}; h2; a href => $uid, ucfirst $self->authInfo->{username}; - txt ' ('.mt('_urank_'.$self->authInfo->{rank}).')'; end; div; a href => "$uid/edit", mt '_menu_myprofile'; br; diff --git a/util/sql/schema.sql b/util/sql/schema.sql index 0a593cec..6cbd2b14 100644 --- a/util/sql/schema.sql +++ b/util/sql/schema.sql @@ -357,7 +357,7 @@ CREATE TABLE users ( id SERIAL NOT NULL PRIMARY KEY, username varchar(20) NOT NULL UNIQUE, mail varchar(100) NOT NULL, - rank smallint NOT NULL DEFAULT 3, + perm smallint NOT NULL DEFAULT 1+4+16, passwd bytea NOT NULL DEFAULT '', registered timestamptz NOT NULL DEFAULT NOW(), c_votes integer NOT NULL DEFAULT 0, diff --git a/util/updates/update_2.20.sql b/util/updates/update_2.20.sql index c4cdb880..390e9a41 100644 --- a/util/updates/update_2.20.sql +++ b/util/updates/update_2.20.sql @@ -39,3 +39,16 @@ CREATE TABLE affiliate_links ( CREATE INDEX affiliate_links_rid ON affiliate_links (rid) WHERE NOT hidden; + + +-- rank -> permissions + +ALTER TABLE users RENAME rank TO perm; +ALTER TABLE users ALTER COLUMN perm SET DEFAULT 1+4+16; +UPDATE users SET perm = CASE + WHEN perm = 2 THEN 1 + WHEN perm = 3 THEN 1+4+16 + WHEN perm = 4 THEN 1+2+4+8+16+32+64 + WHEN perm = 5 THEN 1+2+4+8+16+32+64+128+256 + ELSE 0 END; + -- cgit v1.2.3 From 196e3bd79e08a4f84f9df90e4a88685449b9bee5 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sun, 1 May 2011 10:59:42 +0200 Subject: Bugfix in update_stats_cache() resulting in a 500 --- util/sql/func.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/sql/func.sql b/util/sql/func.sql index 47b4511d..3af04562 100644 --- a/util/sql/func.sql +++ b/util/sql/func.sql @@ -499,7 +499,7 @@ BEGIN UPDATE stats_cache SET count = count+1 WHERE section = TG_TABLE_NAME; ELSE IF TG_TABLE_NAME = 'threads_posts' THEN - IF EXISTS(SELECT 1 FROM threads WHERE id = NEW.tid AND hidden = FALSE) THEN + IF EXISTS(SELECT 1 FROM threads WHERE id = NEW.tid AND threads.hidden = FALSE) THEN UPDATE stats_cache SET count = count+1 WHERE section = TG_TABLE_NAME; END IF; ELSE -- cgit v1.2.3 From 2bf4818105a11abeca313b36d820c3cc397dc5b3 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sun, 1 May 2011 11:07:39 +0200 Subject: Don't show some contribute links when you can't contribute --- lib/VNDB/Handler/VNPage.pm | 14 +++++++++----- lib/VNDB/Util/LayoutHTML.pm | 10 +++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 44a63db8..e10b4414 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -446,11 +446,15 @@ sub _releases { my($self, $v, $r) = @_; div class => 'mainbox releases'; - p class => 'addnew'; - a href => "/c/new?vid=$v->{id}", mt '_vnpage_char_add'; - txt ' | '; - a href => "/v$v->{id}/add", mt '_vnpage_rel_add'; - end; + if($self->authCan('edit')) { + p class => 'addnew'; + if($self->authCan('charedit')) { + a href => "/c/new?vid=$v->{id}", mt '_vnpage_char_add'; + txt ' | '; + } + a href => "/v$v->{id}/add", mt '_vnpage_rel_add'; + end; + } h1 mt '_vnpage_rel'; if(!@$r) { p mt '_vnpage_rel_none'; diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index e1e21924..752f6728 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -99,9 +99,13 @@ sub _menu { a href => "$uid/hist", mt '_menu_mychanges'; br; a href => '/g/links?u='.$self->authInfo->{id}, mt '_menu_mytags'; br; br; - a href => '/v/new', mt '_menu_addvn'; br; - a href => '/p/new', mt '_menu_addproducer'; br; - a href => '/c/new', mt '_menu_addcharacter'; br; + if($self->authCan('edit')) { + a href => '/v/new', mt '_menu_addvn'; br; + a href => '/p/new', mt '_menu_addproducer'; br; + } + if($self->authCan('charedit')) { + a href => '/c/new', mt '_menu_addcharacter'; br; + } br; a href => "$uid/logout", mt '_menu_logout'; end; -- cgit v1.2.3