summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2022-05-27 08:35:26 +0200
committerYorhel <git@yorhel.nl>2022-08-25 10:00:31 +0200
commit5d4ea45a86d8316aeae789f614057795715d9e67 (patch)
treeeb9a0d5962b77d0d339bff4f3cb389fec0ad47b7 /lib
parentb3daafde4a7a1cb4076b9a218e3258d34db313dd (diff)
Staff editions
As discussed in https://vndb.org/t13027 and from https://vndb.org/t6138.327 onwards.
Diffstat (limited to 'lib')
-rw-r--r--lib/VNDB/Types.pm5
-rw-r--r--lib/VNWeb/Staff/Page.pm7
-rw-r--r--lib/VNWeb/User/Edit.pm11
-rw-r--r--lib/VNWeb/VN/Edit.pm15
-rw-r--r--lib/VNWeb/VN/Page.pm94
5 files changed, 105 insertions, 27 deletions
diff --git a/lib/VNDB/Types.pm b/lib/VNDB/Types.pm
index 684c3602..9f61fe2c 100644
--- a/lib/VNDB/Types.pm
+++ b/lib/VNDB/Types.pm
@@ -165,11 +165,14 @@ hash PRODUCER_TYPE =>
# SQL: ENUM credit_type
hash CREDIT_TYPE =>
scenario => 'Scenario',
+ director => 'Director',
chardesign => 'Character design',
art => 'Artist',
music => 'Composer',
songs => 'Vocals',
- director => 'Director',
+ translator => 'Translator',
+ editor => 'Editor',
+ qa => 'Quality assurance',
staff => 'Staff';
diff --git a/lib/VNWeb/Staff/Page.pm b/lib/VNWeb/Staff/Page.pm
index 8d143fcc..d1ee5bf3 100644
--- a/lib/VNWeb/Staff/Page.pm
+++ b/lib/VNWeb/Staff/Page.pm
@@ -74,12 +74,13 @@ sub _roles_ {
my %alias = map +($_->{aid}, $_), $s->{alias}->@*;
my $roles = tuwf->dbAlli(q{
- SELECT v.id, vs.aid, vs.role, vs.note, v.c_released, v.title, v.alttitle
+ SELECT v.id, vs.aid, vs.role, vs.note, ve.name, ve.official, v.c_released, v.title, v.alttitle
FROM vn_staff vs
JOIN vnt v ON v.id = vs.id
+ LEFT JOIN vn_editions ve ON ve.id = vs.id AND ve.eid = vs.eid
WHERE vs.aid IN}, [ keys %alias ], q{
AND NOT v.hidden
- ORDER BY v.c_released ASC, v.title ASC, vs.role ASC
+ ORDER BY v.c_released ASC, v.title ASC, ve.lang NULLS FIRST, ve.name NULLS FIRST, vs.role ASC
});
return if !@$roles;
enrich_ulists_widget $roles;
@@ -101,6 +102,8 @@ sub _roles_ {
td_ class => 'tc_ulist', sub { ulists_widget_ $v if !$vns{$v->{id}}++ } if auth;
td_ class => 'tc1', sub {
a_ href => "/$v->{id}", title => $v->{alttitle}||$v->{title}, shorten $v->{title}, 60;
+ txt_ " $v->{name}" if $v->{name} && $v->{official};
+ b_ class => 'grayedout', " $v->{name}" if $v->{name} && !$v->{official};
};
td_ class => 'tc2', sub { rdate_ $v->{c_released} };
td_ class => 'tc3', $CREDIT_TYPE{$v->{role}};
diff --git a/lib/VNWeb/User/Edit.pm b/lib/VNWeb/User/Edit.pm
index cf544179..c33f04e7 100644
--- a/lib/VNWeb/User/Edit.pm
+++ b/lib/VNWeb/User/Edit.pm
@@ -44,6 +44,9 @@ my $FORM = {
vnrel_langs => { type => 'array', values => { enum => \%LANGUAGE }, sort => 'str', unique => 1 },
vnrel_olang => { anybool => 1 },
vnrel_mtl => { anybool => 1 },
+ staffed_langs => { type => 'array', values => { enum => \%LANGUAGE }, sort => 'str', unique => 1 },
+ staffed_olang => { anybool => 1 },
+ staffed_unoff => { anybool => 1 },
skin => { enum => skins },
customcss => { required => 0, default => '', maxlength => 2000 },
@@ -93,7 +96,8 @@ TUWF::get qr{/$RE{uid}/edit}, sub {
$u->{prefs} = $u->{id} eq auth->uid || auth->permUsermod ?
tuwf->dbRowi(
'SELECT max_sexual, max_violence, traits_sexual, tags_all, tags_cont, tags_ero, tags_tech, prodrelexpand
- , spoilers, vnrel_langs::text[], vnrel_olang, vnrel_mtl, skin, customcss, title_langs, alttitle_langs
+ , vnrel_langs::text[], vnrel_olang, vnrel_mtl, staffed_langs::text[], staffed_olang, staffed_unoff
+ , spoilers, skin, customcss, title_langs, alttitle_langs
, nodistract_noads, nodistract_nofancy, support_enabled, uniname, pubskin_enabled
FROM users u JOIN users_prefs up ON up.id = u.id WHERE u.id =', \$u->{id}
) : undef;
@@ -101,6 +105,7 @@ TUWF::get qr{/$RE{uid}/edit}, sub {
$u->{prefs}{email} = _getmail $u->{id};
$u->{prefs}{skin} ||= config->{skin_default};
$u->{prefs}{vnrel_langs} ||= [ keys %LANGUAGE ];
+ $u->{prefs}{staffed_langs} ||= [ keys %LANGUAGE ];
$u->{prefs}{title_langs} = langpref_parse($u->{prefs}{title_langs}) // $DEFAULT_TITLE_LANGS;
$u->{prefs}{alttitle_langs} = langpref_parse($u->{prefs}{alttitle_langs}) // $DEFAULT_ALTTITLE_LANGS;
$u->{prefs}{traits} = tuwf->dbAlli('SELECT u.tid, t.name, g.name AS "group" FROM users_traits u JOIN traits t ON t.id = u.tid LEFT JOIN traits g ON g.id = t.group WHERE u.id =', \$u->{id}, 'ORDER BY g.order, t.name');
@@ -143,10 +148,12 @@ elm_api UserEdit => $FORM_OUT, $FORM_IN, sub {
$p->{title_langs} = undef if $p->{title_langs} && ($p->{title_langs} eq langpref_fmt($DEFAULT_TITLE_LANGS) || $p->{title_langs} eq '[]');
$p->{alttitle_langs} = undef if $p->{alttitle_langs} && $p->{alttitle_langs} eq langpref_fmt $DEFAULT_ALTTITLE_LANGS;
$p->{vnrel_langs} = $p->{vnrel_langs}->@* == keys %LANGUAGE ? undef : '{'.join(',',$p->{vnrel_langs}->@*).'}';
+ $p->{staffed_langs} = $p->{staffed_langs}->@* == keys %LANGUAGE ? undef : '{'.join(',',$p->{staffed_langs}->@*).'}';
$set{$_} = $p->{$_} for qw/nodistract_noads nodistract_nofancy support_enabled uniname pubskin_enabled/;
$setp{$_} = $p->{$_} for qw/
max_sexual max_violence traits_sexual tags_all tags_cont tags_ero tags_tech prodrelexpand
- vnrel_langs vnrel_olang vnrel_mtl spoilers skin customcss title_langs alttitle_langs
+ vnrel_langs vnrel_olang vnrel_mtl staffed_langs staffed_olang staffed_unoff
+ spoilers skin customcss title_langs alttitle_langs
/;
tuwf->dbExeci('DELETE FROM users_traits WHERE id =', \$data->{id});
tuwf->dbExeci('INSERT INTO users_traits', { id => $data->{id}, tid => $_->{tid} }) for $p->{traits}->@*;
diff --git a/lib/VNWeb/VN/Edit.pm b/lib/VNWeb/VN/Edit.pm
index 0cacbb0f..09608ef7 100644
--- a/lib/VNWeb/VN/Edit.pm
+++ b/lib/VNWeb/VN/Edit.pm
@@ -33,8 +33,15 @@ my $FORM = {
} },
image => { required => 0, vndbid => 'cv' },
image_info => { _when => 'out', required => 0, type => 'hash', keys => $VNWeb::Elm::apis{ImageResult}[0]{aoh} },
- staff => { sort_keys => ['aid','role'], aoh => {
+ editions => { sort_keys => 'eid', aoh => {
+ eid => { uint => 1, max => 500 },
+ lang => { required => 0, language => 1 },
+ name => {},
+ official => { anybool => 1 },
+ } },
+ staff => { sort_keys => ['aid','eid','role'], aoh => {
aid => { id => 1 },
+ eid => { required => 0, uint => 1 },
role => { enum => \%CREDIT_TYPE },
note => { required => 0, default => '', maxlength => 250 },
id => { _when => 'out', vndbid => 's' },
@@ -100,6 +107,8 @@ TUWF::get qr{/$RE{vrev}/edit} => sub {
$e->{staff} = [ grep $_->{id}, $e->{staff}->@* ];
$e->{seiyuu} = [ grep $_->{id}, $e->{seiyuu}->@* ];
+ $e->{editions} = [ sort { ($a->{lang}||'') cmp ($b->{lang}||'') || $b->{official} cmp $a->{official} || $a->{name} cmp $b->{name} } $e->{editions}->@* ];
+
$e->{releases} = releases_by_vn $e->{id};
$e->{chars} = tuwf->dbAlli('
@@ -148,6 +157,10 @@ elm_api VNEdit => $FORM_OUT, $FORM_IN, sub {
validate_dbid 'SELECT aid FROM staff_alias WHERE aid IN', map $_->{aid}, $data->{staff}->@*;
validate_dbid 'SELECT aid FROM staff_alias WHERE aid IN', map $_->{aid}, $data->{seiyuu}->@*;
+ # Drop unused staff editions
+ my %editions = map defined $_->{eid} ? +($_->{eid},1) : (), $data->{staff}->@*;
+ $data->{editions} = [ grep $editions{$_->{eid}}, $data->{editions}->@* ];
+
$data->{relations} = [] if $data->{hidden};
validate_dbid 'SELECT id FROM vn WHERE id IN', map $_->{vid}, $data->{relations}->@*;
die "Relation with self" if grep $_->{vid} eq $e->{id}, $data->{relations}->@*;
diff --git a/lib/VNWeb/VN/Page.pm b/lib/VNWeb/VN/Page.pm
index 77e4883b..e140cb59 100644
--- a/lib/VNWeb/VN/Page.pm
+++ b/lib/VNWeb/VN/Page.pm
@@ -59,7 +59,8 @@ sub enrich_item {
$v->{relations} = [ sort { idcmp($a->{vid}, $b->{vid}) } $v->{relations}->@* ];
$v->{anime} = [ sort { $a->{aid} <=> $b->{aid} } $v->{anime}->@* ];
- $v->{staff} = [ sort { $a->{aid} <=> $b->{aid} || $a->{role} cmp $b->{role} } $v->{staff}->@* ];
+ $v->{editions} = [ sort { ($a->{lang}||'') cmp ($b->{lang}||'') || $b->{official} cmp $a->{official} || $a->{name} cmp $b->{name} } $v->{editions}->@* ];
+ $v->{staff} = [ sort { ($a->{eid}//-1) <=> ($b->{eid}//-1) || $a->{aid} <=> $b->{aid} || $a->{role} cmp $b->{role} } $v->{staff}->@* ];
$v->{seiyuu} = [ sort { $a->{aid} <=> $b->{aid} || idcmp($a->{cid}, $b->{cid}) || $a->{note} cmp $b->{note} } $v->{seiyuu}->@* ];
$v->{screenshots} = [ sort { idcmp($a->{scr}{id}, $b->{scr}{id}) } $v->{screenshots}->@* ];
}
@@ -75,6 +76,25 @@ sub og {
}
+sub prefs {
+ state $default = {
+ vnrel_langs => \%LANGUAGE, vnrel_olang => 1, vnrel_mtl => 0,
+ staffed_langs => \%LANGUAGE, staffed_olang => 1, staffed_unoff => 0,
+ };
+ tuwf->req->{vnpage_prefs} //= auth ? do {
+ my $v = tuwf->dbRowi('
+ SELECT vnrel_langs::text[], vnrel_olang, vnrel_mtl
+ , staffed_langs::text[], staffed_olang, staffed_unoff
+ FROM users_prefs
+ WHERE id =', \auth->uid
+ );
+ $v->{vnrel_langs} = $v->{vnrel_langs} ? { map +($_,1), $v->{langs}->@* } : \%LANGUAGE;
+ $v->{staffed_langs} = $v->{staffed_langs} ? { map +($_,1), $v->{langs}->@* } : \%LANGUAGE;
+ $v
+ } : $default;
+}
+
+
# The voting and review options are hidden if nothing has been released yet.
sub canvote {
my($v) = @_;
@@ -96,7 +116,15 @@ sub rev_ {
[ desc => 'Description' ],
[ devstatus => 'Development status',fmt => \%DEVSTATUS ],
[ length => 'Length', fmt => \%VN_LENGTH ],
+ [ editions => 'Editions', fmt => sub {
+ abbr_ class => "icons lang $_->{lang}", title => $LANGUAGE{$_->{lang}}, '' if $_->{lang};
+ txt_ $_->{name};
+ b_ class => 'grayedout', ' (unofficial)' if !$_->{official};
+ }],
[ staff => 'Credits', fmt => sub {
+ my $eid = $_->{eid};
+ my $e = defined $eid && (grep $eid == $_->{eid}, $_[0]{editions}->@*)[0];
+ txt_ "[$e->{name}] " if $e;
a_ href => "/$_->{sid}", title => $_->{original}||$_->{name}, $_->{name} if $_->{sid};
b_ class => 'grayedout', '[removed alias]' if !$_->{sid};
txt_ " [$CREDIT_TYPE{$_->{role}}]";
@@ -498,8 +526,6 @@ sub tabs_ {
sub releases_ {
my($v) = @_;
- # TODO: Organize a long list of releases a bit better somehow? Collapsable language sections?
-
enrich_release $v->{releases};
$v->{releases} = sort_releases $v->{releases};
@@ -512,18 +538,13 @@ sub releases_ {
}
$langrel{$_} = min map $_->{released}, $lang{$_}->@* for keys %lang;
my @lang = sort { $langrel{$a} <=> $langrel{$b} || ($b eq $v->{olang}) cmp ($a eq $v->{olang}) || $a cmp $b } keys %lang;
-
- my $pref = auth ? do {
- my $v = tuwf->dbRowi('SELECT vnrel_langs::text[] AS langs, vnrel_olang AS olang, vnrel_mtl AS mtl FROM users_prefs WHERE id =', \auth->uid);
- $v->{langs} = $v->{langs} ? { map +($_,1), $v->{langs}->@* } : \%LANGUAGE;
- $v
- } : { langs => \%LANGUAGE, olang => 1, mtl => 0 };
+ my $pref = prefs;
my sub lang_ {
my($lang) = @_;
my $ropt = { id => $lang, lang => $lang };
my $mtl = $langmtl{$lang};
- my $open = ($pref->{olang} && $lang eq $v->{olang} && !$mtl) || ($pref->{langs}{$lang} && (!$mtl || $pref->{mtl}));
+ my $open = ($pref->{vnrel_olang} && $lang eq $v->{olang} && !$mtl) || ($pref->{vnrel_langs}{$lang} && (!$mtl || $pref->{vnrel_mtl}));
details_ open => $open?'open':undef, sub {
summary_ $mtl ? (class => 'mtl') : (), sub {
abbr_ class => "icons lang $lang".($mtl?' mtl':''), title => $LANGUAGE{$lang}, '';
@@ -547,8 +568,8 @@ sub releases_ {
}
-sub staff_ {
- my($v) = @_;
+sub staff_cols_ {
+ my($lst) = @_;
# XXX: The staff listing is included in the page 3 times, for 3 different
# layouts. A better approach to get the same layout is to add the boxes to
@@ -560,7 +581,7 @@ sub staff_ {
# Step 1: Get a list of 'boxes'; Each 'box' represents a role with a list of staff entries.
# @boxes = [ $height, $roleimp, $html ]
my %roles;
- push $roles{$_->{role}}->@*, $_ for grep $_->{sid}, $v->{staff}->@*;
+ push $roles{$_->{role}}->@*, $_ for grep $_->{sid}, @$lst;
my $i=0;
my @boxes =
sort { $b->[0] <=> $a->[0] || $a->[1] <=> $b->[1] }
@@ -569,7 +590,7 @@ sub staff_ {
li_ class => 'vnstaff_head', $CREDIT_TYPE{$_};
li_ sub {
a_ href => "/$_->{sid}", title => $_->{original}||$_->{name}, $_->{name};
- b_ title => $_->{note}, class => 'grayedout', $_->{note} if $_->{note};
+ b_ class => 'grayedout', $_->{note} if $_->{note};
} for sort { $a->{name} cmp $b->{name} } $roles{$_}->@*;
}
], grep $roles{$_}, keys %CREDIT_TYPE;
@@ -591,14 +612,45 @@ sub staff_ {
@$c = sort { $a->[1] <=> $b->[1] } @$c;
}
- div_ class => 'mainbox', id => 'staff', 'data-mainbox-summarize' => 200, sub {
+ div_ class => sprintf('vnstaff-%d', scalar @$_), sub {
+ ul_ sub {
+ lit_ $_->[2] for $_->[2]->@*;
+ } for @$_
+ } for @cols;
+}
+
+
+sub staff_ {
+ my($v) = @_;
+ return if !$v->{staff}->@*;
+
+ my %staff;
+ push $staff{ $_->{eid} // '' }->@*, $_ for $v->{staff}->@*;
+ my $pref = prefs;
+
+ div_ class => 'mainbox vnstaff', id => 'staff', sub {
h1_ 'Staff';
- div_ class => sprintf('vnstaff vnstaff-%d', scalar @$_), sub {
- ul_ sub {
- lit_ $_->[2] for $_->[2]->@*;
- } for @$_
- } for @cols;
- } if $v->{staff}->@*;
+ if (!$v->{editions}->@*) {
+ staff_cols_ $v->{staff};
+ return;
+ }
+ for my $e (undef, $v->{editions}->@*) {
+ my $lst = $staff{ $e ? $e->{eid} : '' };
+ next if !$lst;
+ my $lang = ($e && $e->{lang}) || $v->{olang};
+ my $unoff = $e && !$e->{official};
+ my $open = ($pref->{staffed_olang} && !$e) || ($pref->{staffed_langs}{$lang} && (!$unoff || $pref->{staffed_mtl}));
+ details_ open => $open?'open':undef, sub {
+ summary_ sub {
+ abbr_ class => "icons lang $e->{lang}", title => $LANGUAGE{$e->{lang}}, '' if $e && $e->{lang};
+ txt_ 'Original edition' if !$e;
+ txt_ $e->{name} if $e;
+ b_ class => 'grayedout', ' (unofficial)' if $unoff;
+ };
+ staff_cols_ $lst;
+ };
+ }
+ };
}