summaryrefslogtreecommitdiff
path: root/lib/VNWeb
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-07-13 11:32:52 +0200
committerYorhel <git@yorhel.nl>2020-07-13 11:32:54 +0200
commitf23f9a67e17c6678bcf7ff7a32b867ba0ee80962 (patch)
tree94cd398b1efd0d6b3737b99ef85413f39c61abde /lib/VNWeb
parent4a3daf884119a57cd5c8bb4acda2a2c502a372ae (diff)
Refactor: Split VNWeb::User::Lists into its own VNWeb::ULists::*
It's not exactly a tiny feature, after all. ULists::Elm should really be split up further, too, and the sharing of structures between ULists::Elm and ULists::List is kind of ugly at the moment, but I may get to that later.
Diffstat (limited to 'lib/VNWeb')
-rw-r--r--lib/VNWeb/Releases/Lib.pm2
-rw-r--r--lib/VNWeb/Releases/Page.pm2
-rw-r--r--lib/VNWeb/ULists/Elm.pm252
-rw-r--r--lib/VNWeb/ULists/Lib.pm13
-rw-r--r--lib/VNWeb/ULists/List.pm (renamed from lib/VNWeb/User/Lists.pm)275
5 files changed, 278 insertions, 266 deletions
diff --git a/lib/VNWeb/Releases/Lib.pm b/lib/VNWeb/Releases/Lib.pm
index 7b36a290..234de176 100644
--- a/lib/VNWeb/Releases/Lib.pm
+++ b/lib/VNWeb/Releases/Lib.pm
@@ -96,7 +96,7 @@ sub release_row_ {
td_ class => 'tc_icons', sub { icons_ $r };
td_ class => 'tc_prod', join ' & ', $r->{publisher} ? 'Pub' : (), $r->{developer} ? 'Dev' : () if $prodpage;
td_ class => 'tc5 elm_dd_left', sub {
- elm_ 'UList.ReleaseEdit', $VNWeb::User::Lists::RLIST_STATUS, { rid => $r->{id}, uid => auth->uid, status => $r->{rlist_status}, empty => '--' } if auth;
+ elm_ 'UList.ReleaseEdit', $VNWeb::ULists::Elm::RLIST_STATUS, { rid => $r->{id}, uid => auth->uid, status => $r->{rlist_status}, empty => '--' } if auth;
};
td_ class => 'tc6', sub { release_extlinks_ $r, "${id}_$r->{id}" };
}
diff --git a/lib/VNWeb/Releases/Page.pm b/lib/VNWeb/Releases/Page.pm
index ccf4b6fb..d7cbb745 100644
--- a/lib/VNWeb/Releases/Page.pm
+++ b/lib/VNWeb/Releases/Page.pm
@@ -195,7 +195,7 @@ sub _infotable_ {
td_ sub {
div_ class => 'elm_dd_input', style => 'width: 150px', sub {
my $d = tuwf->dbVali('SELECT status FROM rlists WHERE', { rid => $r->{id}, uid => auth->uid });
- elm_ 'UList.ReleaseEdit', $VNWeb::User::Lists::RLIST_STATUS, { rid => $r->{id}, uid => auth->uid, status => $d, empty => 'not on your list' };
+ elm_ 'UList.ReleaseEdit', $VNWeb::ULists::Elm::RLIST_STATUS, { rid => $r->{id}, uid => auth->uid, status => $d, empty => 'not on your list' };
}
};
} if auth;
diff --git a/lib/VNWeb/ULists/Elm.pm b/lib/VNWeb/ULists/Elm.pm
new file mode 100644
index 00000000..0dd546c6
--- /dev/null
+++ b/lib/VNWeb/ULists/Elm.pm
@@ -0,0 +1,252 @@
+package VNWeb::ULists::Elm;
+
+use VNWeb::Prelude;
+use VNWeb::ULists::Lib;
+
+
+# Should be called after any change to the ulist_* tables.
+# (Normally I'd do this with triggers, but that seemed like a more complex and less efficient solution in this case)
+sub updcache {
+ tuwf->dbExeci(SELECT => sql_func update_users_ulist_stats => \shift);
+}
+
+
+our $LABELS = form_compile any => {
+ uid => { id => 1 },
+ labels => { aoh => {
+ id => { int => 1 },
+ label => { maxlength => 50 },
+ private => { anybool => 1 },
+ count => { uint => 1 },
+ delete => { required => 0, default => undef, uint => 1, range => [1, 3] }, # 1=keep vns, 2=delete when no other label, 3=delete all
+ } }
+};
+
+elm_api UListManageLabels => undef, $LABELS, sub {
+ my($uid, $labels) = ($_[0]{uid}, $_[0]{labels});
+ return elm_Unauth if !ulists_own $uid;
+
+ # Insert new labels
+ my @new = grep $_->{id} < 0 && !$_->{delete}, @$labels;
+ # Subquery to get the lowest unused id
+ my $newid = sql '(
+ SELECT min(x.n)
+ FROM generate_series(10,
+ greatest((SELECT max(id)+1 from ulist_labels ul WHERE ul.uid =', \$uid, '), 10)
+ ) x(n)
+ WHERE NOT EXISTS(SELECT 1 FROM ulist_labels ul WHERE ul.uid =', \$uid, 'AND ul.id = x.n)
+ )';
+ tuwf->dbExeci('INSERT INTO ulist_labels', { id => $newid, uid => $uid, label => $_->{label}, private => $_->{private} }) for @new;
+
+ # Update private flag
+ tuwf->dbExeci(
+ 'UPDATE ulist_labels SET private =', \$_->{private},
+ 'WHERE uid =', \$uid, 'AND id =', \$_->{id}, 'AND private <>', \$_->{private}
+ ) for grep $_->{id} > 0 && !$_->{delete}, @$labels;
+
+ # Update label
+ tuwf->dbExeci(
+ 'UPDATE ulist_labels SET label =', \$_->{label},
+ 'WHERE uid =', \$uid, 'AND id =', \$_->{id}, 'AND label <>', \$_->{label}
+ ) for grep $_->{id} >= 10 && !$_->{delete}, @$labels;
+
+ # Delete labels
+ my @delete = grep $_->{id} >= 10 && $_->{delete}, @$labels;
+ my @delete_lblonly = map $_->{id}, grep $_->{delete} == 1, @delete;
+ my @delete_empty = map $_->{id}, grep $_->{delete} == 2, @delete;
+ my @delete_all = map $_->{id}, grep $_->{delete} == 3, @delete;
+
+ # delete vns with: (a label in option 3) OR ((a label in option 2) AND (no labels other than in option 1 or 2))
+ my @where =
+ @delete_all ? sql('vid IN(SELECT vid FROM ulist_vns_labels WHERE uid =', \$uid, 'AND lbl IN', \@delete_all, ')') : (),
+ @delete_empty ? sql(
+ 'vid IN(SELECT vid FROM ulist_vns_labels WHERE uid =', \$uid, 'AND lbl IN', \@delete_empty, ')',
+ 'AND NOT EXISTS(SELECT 1 FROM ulist_vns_labels WHERE uid =', \$uid, 'AND lbl NOT IN(', [ @delete_lblonly, @delete_empty ], '))'
+ ) : ();
+ tuwf->dbExeci('DELETE FROM ulist_vns WHERE uid =', \$uid, 'AND (', sql_or(@where), ')') if @where;
+
+ # (This will also delete all relevant vn<->label rows from ulist_vns_labels)
+ tuwf->dbExeci('DELETE FROM ulist_labels WHERE uid =', \$uid, 'AND id IN', [ map $_->{id}, @delete ]) if @delete;
+
+ updcache $uid;
+ elm_Success
+};
+
+
+
+
+our $VNVOTE = form_compile any => {
+ uid => { id => 1 },
+ vid => { id => 1 },
+ vote => { vnvote => 1 },
+};
+
+elm_api UListVoteEdit => undef, $VNVOTE, sub {
+ my($data) = @_;
+ return elm_Unauth if !ulists_own $data->{uid};
+ tuwf->dbExeci(
+ 'INSERT INTO ulist_vns', { %$data, vote_date => sql $data->{vote} ? 'NOW()' : 'NULL' },
+ 'ON CONFLICT (uid, vid) DO UPDATE
+ SET', { %$data,
+ lastmod => sql('NOW()'),
+ vote_date => sql $data->{vote} ? 'CASE WHEN ulist_vns.vote IS NULL THEN NOW() ELSE ulist_vns.vote_date END' : 'NULL'
+ }
+ );
+ updcache $data->{uid};
+ elm_Success
+};
+
+
+
+
+my $VNLABELS = {
+ uid => { id => 1 },
+ vid => { id => 1 },
+ label => { _when => 'in', id => 1 },
+ applied => { _when => 'in', anybool => 1 },
+ labels => { _when => 'out', aoh => { id => { int => 1 }, label => {}, private => { anybool => 1 } } },
+ selected => { _when => 'out', type => 'array', values => { id => 1 } },
+};
+
+our $VNLABELS_OUT = form_compile out => $VNLABELS;
+my $VNLABELS_IN = form_compile in => $VNLABELS;
+
+elm_api UListLabelEdit => $VNLABELS_OUT, $VNLABELS_IN, sub {
+ my($data) = @_;
+ return elm_Unauth if !ulists_own $data->{uid};
+ die "Attempt to set vote label" if $data->{label} == 7;
+
+ tuwf->dbExeci('INSERT INTO ulist_vns', {uid => $data->{uid}, vid => $data->{vid}}, 'ON CONFLICT (uid, vid) DO NOTHING');
+ tuwf->dbExeci(
+ 'DELETE FROM ulist_vns_labels
+ WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid}, 'AND lbl =', \$data->{label}
+ ) if !$data->{applied};
+ tuwf->dbExeci(
+ 'INSERT INTO ulist_vns_labels', { uid => $data->{uid}, vid => $data->{vid}, lbl => $data->{label} },
+ 'ON CONFLICT (uid, vid, lbl) DO NOTHING'
+ ) if $data->{applied};
+ tuwf->dbExeci('UPDATE ulist_vns SET lastmod = NOW() WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid});
+
+ updcache $data->{uid};
+ elm_Success
+};
+
+
+
+
+our $VNDATE = form_compile any => {
+ uid => { id => 1 },
+ vid => { id => 1 },
+ date => { required => 0, default => '', regex => qr/^(?:19[7-9][0-9]|20[0-9][0-9])-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])$/ }, # 1970 - 2099 for sanity
+ start => { anybool => 1 }, # Field selection, started/finished
+};
+
+elm_api UListDateEdit => undef, $VNDATE, sub {
+ my($data) = @_;
+ return elm_Unauth if !ulists_own $data->{uid};
+ tuwf->dbExeci(
+ 'UPDATE ulist_vns SET lastmod = NOW(), ', $data->{start} ? 'started' : 'finished', '=', \($data->{date}||undef),
+ 'WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid}
+ );
+ updcache $data->{uid};
+ elm_Success
+};
+
+
+
+
+our $VNOPT = form_compile any => {
+ own => { anybool => 1 },
+ uid => { id => 1 },
+ vid => { id => 1 },
+ notes => {},
+ rels => $VNWeb::Elm::apis{Releases}[0],
+ relstatus => { type => 'array', values => { uint => 1 } }, # List of release statuses, same order as rels
+};
+
+
+
+# UListVNNotes module is abused for the UList.Opts flag definition
+elm_api UListVNNotes => $VNOPT, {
+ uid => { id => 1 },
+ vid => { id => 1 },
+ notes => { required => 0, default => '', maxlength => 2000 },
+}, sub {
+ my($data) = @_;
+ return elm_Unauth if !ulists_own $data->{uid};
+ tuwf->dbExeci(
+ 'INSERT INTO ulist_vns', \%$data, 'ON CONFLICT (uid, vid) DO UPDATE SET', { %$data, lastmod => sql('NOW()') }
+ );
+ # Doesn't need `updcache()`
+ elm_Success
+};
+
+
+
+
+elm_api UListDel => undef, {
+ uid => { id => 1 },
+ vid => { id => 1 },
+}, sub {
+ my($data) = @_;
+ return elm_Unauth if !ulists_own $data->{uid};
+ tuwf->dbExeci('DELETE FROM ulist_vns WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid});
+ updcache $data->{uid};
+ elm_Success
+};
+
+
+
+
+# Adds the release when not in the list.
+# $RLIST_STATUS is also referenced from VNWeb::Releases::Page.
+our $RLIST_STATUS = form_compile any => {
+ uid => { id => 1 },
+ rid => { id => 1 },
+ status => { required => 0, uint => 1, enum => \%RLIST_STATUS }, # undef meaning delete
+ empty => { required => 0, default => '' }, # An 'out' field
+};
+elm_api UListRStatus => undef, $RLIST_STATUS, sub {
+ my($data) = @_;
+ delete $data->{empty};
+ return elm_Unauth if !ulists_own $data->{uid};
+ if(!defined $data->{status}) {
+ tuwf->dbExeci('DELETE FROM rlists WHERE uid =', \$data->{uid}, 'AND rid =', \$data->{rid})
+ } else {
+ tuwf->dbExeci('INSERT INTO rlists', $data, 'ON CONFLICT (uid, rid) DO UPDATE SET status =', \$data->{status})
+ }
+ # Doesn't need `updcache()`
+ elm_Success
+};
+
+
+
+
+our %SAVED_OPTS = (
+ # Labels
+ l => { onerror => [], type => 'array', scalar => 1, values => { int => 1 } },
+ mul => { anybool => 1 },
+ # Sort column & order
+ s => { onerror => 'title', enum => [qw[ title label vote voted added modified started finished rel rating ]] },
+ o => { onerror => 'a', enum => ['a', 'd'] },
+ # Visible columns
+ c => { onerror => [], type => 'array', scalar => 1, values => { enum => [qw[ label vote voted added modified started finished rel rating ]] } },
+);
+
+my $SAVED_OPTS = {
+ uid => { id => 1 },
+ opts => { type => 'hash', keys => \%SAVED_OPTS },
+ field => { _when => 'in', enum => [qw/ vnlist votes wish /] },
+};
+
+my $SAVED_OPTS_IN = form_compile in => $SAVED_OPTS;
+our $SAVED_OPTS_OUT = form_compile out => $SAVED_OPTS;
+
+elm_api UListSaveDefault => $SAVED_OPTS_OUT, $SAVED_OPTS_IN, sub {
+ my($data) = @_;
+ return elm_Unauth if !ulists_own $data->{uid};
+ tuwf->dbExeci('UPDATE users SET ulist_'.$data->{field}, '=', \JSON::XS->new->encode($data->{opts}), 'WHERE id =', \$data->{uid});
+ elm_Success
+};
+
+1;
diff --git a/lib/VNWeb/ULists/Lib.pm b/lib/VNWeb/ULists/Lib.pm
new file mode 100644
index 00000000..d831692a
--- /dev/null
+++ b/lib/VNWeb/ULists/Lib.pm
@@ -0,0 +1,13 @@
+package VNWeb::ULists::Lib;
+
+use VNWeb::Prelude;
+use Exporter 'import';
+
+our @EXPORT = qw/ulists_own/;
+
+# Do we have "ownership" access to this users' list (i.e. can we edit and see private stuff)?
+sub ulists_own {
+ auth->permUsermod || (auth && auth->uid == shift)
+}
+
+1;
diff --git a/lib/VNWeb/User/Lists.pm b/lib/VNWeb/ULists/List.pm
index ff287c5e..a451e73c 100644
--- a/lib/VNWeb/User/Lists.pm
+++ b/lib/VNWeb/ULists/List.pm
@@ -1,263 +1,10 @@
-package VNWeb::User::Lists;
+package VNWeb::ULists::Main;
use VNWeb::Prelude;
+use VNWeb::ULists::Lib;
use POSIX 'strftime';
-# Do we have "ownership" access to this users' list (i.e. can we edit and see private stuff)?
-sub own {
- auth->permUsermod || (auth && auth->uid == shift)
-}
-
-
-# Should be called after any change to the ulist_* tables.
-# (Normally I'd do this with triggers, but that seemed like a more complex and less efficient solution in this case)
-sub updcache {
- tuwf->dbExeci(SELECT => sql_func update_users_ulist_stats => \shift);
-}
-
-
-my $LABELS = form_compile any => {
- uid => { id => 1 },
- labels => { aoh => {
- id => { int => 1 },
- label => { maxlength => 50 },
- private => { anybool => 1 },
- count => { uint => 1 },
- delete => { required => 0, default => undef, uint => 1, range => [1, 3] }, # 1=keep vns, 2=delete when no other label, 3=delete all
- } }
-};
-
-elm_api UListManageLabels => undef, $LABELS, sub {
- my($uid, $labels) = ($_[0]{uid}, $_[0]{labels});
- return elm_Unauth if !own $uid;
-
- # Insert new labels
- my @new = grep $_->{id} < 0 && !$_->{delete}, @$labels;
- # Subquery to get the lowest unused id
- my $newid = sql '(
- SELECT min(x.n)
- FROM generate_series(10,
- greatest((SELECT max(id)+1 from ulist_labels ul WHERE ul.uid =', \$uid, '), 10)
- ) x(n)
- WHERE NOT EXISTS(SELECT 1 FROM ulist_labels ul WHERE ul.uid =', \$uid, 'AND ul.id = x.n)
- )';
- tuwf->dbExeci('INSERT INTO ulist_labels', { id => $newid, uid => $uid, label => $_->{label}, private => $_->{private} }) for @new;
-
- # Update private flag
- tuwf->dbExeci(
- 'UPDATE ulist_labels SET private =', \$_->{private},
- 'WHERE uid =', \$uid, 'AND id =', \$_->{id}, 'AND private <>', \$_->{private}
- ) for grep $_->{id} > 0 && !$_->{delete}, @$labels;
-
- # Update label
- tuwf->dbExeci(
- 'UPDATE ulist_labels SET label =', \$_->{label},
- 'WHERE uid =', \$uid, 'AND id =', \$_->{id}, 'AND label <>', \$_->{label}
- ) for grep $_->{id} >= 10 && !$_->{delete}, @$labels;
-
- # Delete labels
- my @delete = grep $_->{id} >= 10 && $_->{delete}, @$labels;
- my @delete_lblonly = map $_->{id}, grep $_->{delete} == 1, @delete;
- my @delete_empty = map $_->{id}, grep $_->{delete} == 2, @delete;
- my @delete_all = map $_->{id}, grep $_->{delete} == 3, @delete;
-
- # delete vns with: (a label in option 3) OR ((a label in option 2) AND (no labels other than in option 1 or 2))
- my @where =
- @delete_all ? sql('vid IN(SELECT vid FROM ulist_vns_labels WHERE uid =', \$uid, 'AND lbl IN', \@delete_all, ')') : (),
- @delete_empty ? sql(
- 'vid IN(SELECT vid FROM ulist_vns_labels WHERE uid =', \$uid, 'AND lbl IN', \@delete_empty, ')',
- 'AND NOT EXISTS(SELECT 1 FROM ulist_vns_labels WHERE uid =', \$uid, 'AND lbl NOT IN(', [ @delete_lblonly, @delete_empty ], '))'
- ) : ();
- tuwf->dbExeci('DELETE FROM ulist_vns WHERE uid =', \$uid, 'AND (', sql_or(@where), ')') if @where;
-
- # (This will also delete all relevant vn<->label rows from ulist_vns_labels)
- tuwf->dbExeci('DELETE FROM ulist_labels WHERE uid =', \$uid, 'AND id IN', [ map $_->{id}, @delete ]) if @delete;
-
- updcache $uid;
- elm_Success
-};
-
-
-
-
-my $VNVOTE = form_compile any => {
- uid => { id => 1 },
- vid => { id => 1 },
- vote => { vnvote => 1 },
-};
-
-elm_api UListVoteEdit => undef, $VNVOTE, sub {
- my($data) = @_;
- return elm_Unauth if !own $data->{uid};
- tuwf->dbExeci(
- 'INSERT INTO ulist_vns', { %$data, vote_date => sql $data->{vote} ? 'NOW()' : 'NULL' },
- 'ON CONFLICT (uid, vid) DO UPDATE
- SET', { %$data,
- lastmod => sql('NOW()'),
- vote_date => sql $data->{vote} ? 'CASE WHEN ulist_vns.vote IS NULL THEN NOW() ELSE ulist_vns.vote_date END' : 'NULL'
- }
- );
- updcache $data->{uid};
- elm_Success
-};
-
-
-
-
-my $VNLABELS = {
- uid => { id => 1 },
- vid => { id => 1 },
- label => { _when => 'in', id => 1 },
- applied => { _when => 'in', anybool => 1 },
- labels => { _when => 'out', aoh => { id => { int => 1 }, label => {}, private => { anybool => 1 } } },
- selected => { _when => 'out', type => 'array', values => { id => 1 } },
-};
-
-my $VNLABELS_OUT = form_compile out => $VNLABELS;
-my $VNLABELS_IN = form_compile in => $VNLABELS;
-
-elm_api UListLabelEdit => $VNLABELS_OUT, $VNLABELS_IN, sub {
- my($data) = @_;
- return elm_Unauth if !own $data->{uid};
- die "Attempt to set vote label" if $data->{label} == 7;
-
- tuwf->dbExeci('INSERT INTO ulist_vns', {uid => $data->{uid}, vid => $data->{vid}}, 'ON CONFLICT (uid, vid) DO NOTHING');
- tuwf->dbExeci(
- 'DELETE FROM ulist_vns_labels
- WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid}, 'AND lbl =', \$data->{label}
- ) if !$data->{applied};
- tuwf->dbExeci(
- 'INSERT INTO ulist_vns_labels', { uid => $data->{uid}, vid => $data->{vid}, lbl => $data->{label} },
- 'ON CONFLICT (uid, vid, lbl) DO NOTHING'
- ) if $data->{applied};
- tuwf->dbExeci('UPDATE ulist_vns SET lastmod = NOW() WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid});
-
- updcache $data->{uid};
- elm_Success
-};
-
-
-
-
-my $VNDATE = form_compile any => {
- uid => { id => 1 },
- vid => { id => 1 },
- date => { required => 0, default => '', regex => qr/^(?:19[7-9][0-9]|20[0-9][0-9])-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])$/ }, # 1970 - 2099 for sanity
- start => { anybool => 1 }, # Field selection, started/finished
-};
-
-elm_api UListDateEdit => undef, $VNDATE, sub {
- my($data) = @_;
- return elm_Unauth if !own $data->{uid};
- tuwf->dbExeci(
- 'UPDATE ulist_vns SET lastmod = NOW(), ', $data->{start} ? 'started' : 'finished', '=', \($data->{date}||undef),
- 'WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid}
- );
- updcache $data->{uid};
- elm_Success
-};
-
-
-
-
-my $VNOPT = form_compile any => {
- own => { anybool => 1 },
- uid => { id => 1 },
- vid => { id => 1 },
- notes => {},
- rels => $VNWeb::Elm::apis{Releases}[0],
- relstatus => { type => 'array', values => { uint => 1 } }, # List of release statuses, same order as rels
-};
-
-
-
-# UListVNNotes module is abused for the UList.Opts flag definition
-elm_api UListVNNotes => $VNOPT, {
- uid => { id => 1 },
- vid => { id => 1 },
- notes => { required => 0, default => '', maxlength => 2000 },
-}, sub {
- my($data) = @_;
- return elm_Unauth if !own $data->{uid};
- tuwf->dbExeci(
- 'INSERT INTO ulist_vns', \%$data, 'ON CONFLICT (uid, vid) DO UPDATE SET', { %$data, lastmod => sql('NOW()') }
- );
- # Doesn't need `updcache()`
- elm_Success
-};
-
-
-
-
-elm_api UListDel => undef, {
- uid => { id => 1 },
- vid => { id => 1 },
-}, sub {
- my($data) = @_;
- return elm_Unauth if !own $data->{uid};
- tuwf->dbExeci('DELETE FROM ulist_vns WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid});
- updcache $data->{uid};
- elm_Success
-};
-
-
-
-
-# Adds the release when not in the list.
-# $RLIST_STATUS is also referenced from VNWeb::Releases::Page.
-our $RLIST_STATUS = form_compile any => {
- uid => { id => 1 },
- rid => { id => 1 },
- status => { required => 0, uint => 1, enum => \%RLIST_STATUS }, # undef meaning delete
- empty => { required => 0, default => '' }, # An 'out' field
-};
-elm_api UListRStatus => undef, $RLIST_STATUS, sub {
- my($data) = @_;
- delete $data->{empty};
- return elm_Unauth if !own $data->{uid};
- if(!defined $data->{status}) {
- tuwf->dbExeci('DELETE FROM rlists WHERE uid =', \$data->{uid}, 'AND rid =', \$data->{rid})
- } else {
- tuwf->dbExeci('INSERT INTO rlists', $data, 'ON CONFLICT (uid, rid) DO UPDATE SET status =', \$data->{status})
- }
- # Doesn't need `updcache()`
- elm_Success
-};
-
-
-
-
-my %SAVED_OPTS = (
- # Labels
- l => { onerror => [], type => 'array', scalar => 1, values => { int => 1 } },
- mul => { anybool => 1 },
- # Sort column & order
- s => { onerror => 'title', enum => [qw[ title label vote voted added modified started finished rel rating ]] },
- o => { onerror => 'a', enum => ['a', 'd'] },
- # Visible columns
- c => { onerror => [], type => 'array', scalar => 1, values => { enum => [qw[ label vote voted added modified started finished rel rating ]] } },
-);
-
-my $SAVED_OPTS = {
- uid => { id => 1 },
- opts => { type => 'hash', keys => \%SAVED_OPTS },
- field => { _when => 'in', enum => [qw/ vnlist votes wish /] },
-};
-
-my $SAVED_OPTS_IN = form_compile in => $SAVED_OPTS;
-my $SAVED_OPTS_OUT = form_compile out => $SAVED_OPTS;
-
-elm_api UListSaveDefault => $SAVED_OPTS_OUT, $SAVED_OPTS_IN, sub {
- my($data) = @_;
- return elm_Unauth if !own $data->{uid};
- tuwf->dbExeci('UPDATE users SET ulist_'.$data->{field}, '=', \JSON::XS->new->encode($data->{opts}), 'WHERE id =', \$data->{uid});
- elm_Success
-};
-
-
-
-
sub opt {
my($u, $filtlabels) = @_;
@@ -273,7 +20,7 @@ sub opt {
p => { upage => 1 },
ch=> { onerror => undef, enum => [ 'a'..'z', 0 ] },
q => { onerror => undef },
- %SAVED_OPTS
+ %VNWeb::ULists::Elm::SAVED_OPTS
)->data;
# $labels only includes labels we are allowed to see, getting rid of any labels in 'l' that aren't in $labels ensures we only filter on visible labels
@@ -364,7 +111,7 @@ sub vn_ {
td_ mkclass(tc_vote => 1, compact => $own, stealth => $own), sub {
txt_ fmtvote $v->{vote} if !$own;
- elm_ 'UList.VoteEdit' => $VNVOTE, { uid => $uid, vid => $v->{id}, vote => fmtvote($v->{vote}) }, fmtvote $v->{vote}
+ elm_ 'UList.VoteEdit' => $VNWeb::ULists::Elm::VNVOTE, { uid => $uid, vid => $v->{id}, vote => fmtvote($v->{vote}) }, fmtvote $v->{vote}
if $own && ($v->{vote} || sprintf('%08d', $v->{c_released}||0) < strftime '%Y%m%d', gmtime);
} if in vote => $opt->{c};
@@ -377,7 +124,7 @@ sub vn_ {
my @l = grep $labels{$_->{id}} && $_->{id} != 7, @$labels;
my $txt = @l ? join ', ', map $_->{label}, @l : '-';
if($own) {
- elm_ 'UList.LabelEdit' => $VNLABELS_OUT, { vid => $v->{id}, selected => [ grep $_ != 7, $v->{labels}->@* ] }, $txt;
+ elm_ 'UList.LabelEdit' => $VNWeb::ULists::Elm::VNLABELS_OUT, { vid => $v->{id}, selected => [ grep $_ != 7, $v->{labels}->@* ] }, $txt;
} else {
txt_ $txt;
}
@@ -393,12 +140,12 @@ sub vn_ {
td_ class => 'tc_started', sub {
txt_ $v->{started}||'' if !$own;
- elm_ 'UList.DateEdit' => $VNDATE, { uid => $uid, vid => $v->{id}, date => $v->{started}||'', start => 1 }, $v->{started}||'' if $own;
+ elm_ 'UList.DateEdit' => $VNWeb::ULists::Elm::VNDATE, { uid => $uid, vid => $v->{id}, date => $v->{started}||'', start => 1 }, $v->{started}||'' if $own;
} if in started => $opt->{c};
td_ class => 'tc_finished', sub {
txt_ $v->{finished}||'' if !$own;
- elm_ 'UList.DateEdit' => $VNDATE, { uid => $uid, vid => $v->{id}, date => $v->{finished}||'', start => 0 }, $v->{finished}||'' if $own;
+ elm_ 'UList.DateEdit' => $VNWeb::ULists::Elm::VNDATE, { uid => $uid, vid => $v->{id}, date => $v->{finished}||'', start => 0 }, $v->{finished}||'' if $own;
} if in finished => $opt->{c};
td_ class => 'tc_rel', sub { rdate_ $v->{c_released} } if in rel => $opt->{c};
@@ -407,7 +154,7 @@ sub vn_ {
tr_ mkclass(hidden => 1, 'collapsed_vid'.$v->{id} => 1, odd => $n % 2 == 0), sub {
td_ colspan => 7, class => 'tc_opt', sub {
my $relstatus = [ map $_->{status}, $v->{rels}->@* ];
- elm_ 'UList.Opt' => $VNOPT, { own => $own, uid => $uid, vid => $v->{id}, notes => $v->{notes}, rels => $v->{rels}, relstatus => $relstatus };
+ elm_ 'UList.Opt' => $VNWeb::ULists::Elm::VNOPT, { own => $own, uid => $uid, vid => $v->{id}, notes => $v->{notes}, rels => $v->{rels}, relstatus => $relstatus };
};
};
}
@@ -517,7 +264,7 @@ TUWF::get qr{/$RE{uid}/ulist}, sub {
my $u = tuwf->dbRowi('SELECT id,', sql_user(), ', ulist_votes, ulist_vnlist, ulist_wish FROM users u WHERE id =', \tuwf->capture('id'));
return tuwf->resNotFound if !$u->{id};
- my $own = own $u->{id};
+ my $own = ulists_own $u->{id};
# Visible and selectable labels
my $labels = tuwf->dbAlli(
@@ -562,7 +309,7 @@ TUWF::get qr{/$RE{uid}/ulist}, sub {
framework_ title => $title, type => 'u', dbobj => $u, tab => $tab, js => 1,
$own ? ( pagevars => {
uid => $u->{id}*1,
- labels => $LABELS->analyze->{keys}{labels}->coerce_for_json($labels),
+ labels => $VNWeb::ULists::Elm::LABELS->analyze->{keys}{labels}->coerce_for_json($labels),
voteprivate => (map \($_->{private}?1:0), grep $_->{id} == 7, @$labels),
} ) : (),
sub {
@@ -576,7 +323,7 @@ TUWF::get qr{/$RE{uid}/ulist}, sub {
} else {
filters_ $own, $filtlabels, $opt, $opt_labels, \&url;
elm_ 'UList.ManageLabels' if $own;
- elm_ 'UList.SaveDefault', $SAVED_OPTS_OUT, { uid => $u->{id}, opts => $opt } if $own;
+ elm_ 'UList.SaveDefault', $VNWeb::ULists::Elm::SAVED_OPTS_OUT, { uid => $u->{id}, opts => $opt } if $own;
}
};
listing_ $u->{id}, $own, $opt, $labels, \&url if !$empty;