diff options
author | Yorhel <git@yorhel.nl> | 2019-10-19 15:12:43 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2019-11-10 12:44:55 +0100 |
commit | 2eff1dc7ad645cf51252d5a64275bcfc783fc325 (patch) | |
tree | cd993e754e98583508cd94f2a4869d1b64587c83 /lib/VNWeb | |
parent | 2d0a71b5083192a06de9e47a4424546a6bc4b639 (diff) |
ulist: Add data model for new lists + Perl/Elm for label management
Very much experimental. I'm not sure this is even the right model.
Diffstat (limited to 'lib/VNWeb')
-rw-r--r-- | lib/VNWeb/User/Lists.pm | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/lib/VNWeb/User/Lists.pm b/lib/VNWeb/User/Lists.pm new file mode 100644 index 00000000..9ce5cf10 --- /dev/null +++ b/lib/VNWeb/User/Lists.pm @@ -0,0 +1,119 @@ +package VNWeb::User::Lists; + +use VNWeb::Prelude; + +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_form 'ManageLabels', undef, $LABELS; + + +# TODO: Keep this URL? Steal /u+/list when that one's gone? +TUWF::get qr{/$RE{uid}/ulist}, sub { + my $u = tuwf->dbRowi('SELECT id,', sql_user(), 'FROM users u WHERE id =', \tuwf->capture('id')); + return tuwf->resNotFound if !$u->{id}; + + my $own = auth && $u->{id} == auth->uid; + my $labels = tuwf->dbAlli( + 'SELECT l.id, l.label, l.private, count(vl.vid) as count, null as delete + FROM ulists_labels l LEFT JOIN ulists_vn_labels vl ON vl.uid = l.uid AND vl.lbl = l.id + WHERE', { 'l.uid' => $u->{id}, $own ? () : ('l.private' => 0) }, + 'GROUP BY l.id, l.label, l.private + ORDER BY CASE WHEN l.id < 1000 THEN l.id ELSE 1000 END, l.label' + ); + + my sub lblfilt_ { + input_ type => 'checkbox', name => 'l', value => $_->{id}, id => "form_l$_->{id}", 0 ? (checked => 'checked') : (); + label_ for => "form_l$_->{id}", "$_->{label} "; + txt_ " ($_->{count})" if !$_->{private}; + b_ class => 'grayedout', " ($_->{count})" if $_->{private}; + } + + my $title = $own ? 'My list' : user_displayname($u)."'s list"; + framework_ title => $title, type => 'u', dbobj => $u, tab => 'list', + sub { + div_ class => 'mainbox', sub { + h1_ $title; + form_ method => 'get', sub { + p_ class => 'labelfilters', sub { + span_ class => 'linkradio', sub { + join_ sub { em_ ' / ' }, \&lblfilt_, grep $_->{id} < 1000, @$labels; + em_ ' | '; + input_ type => 'checkbox', name => 'l', class => 'checkall', value => 0, id => 'form_l_all'; + label_ for => 'form_l_all', 'Select all'; + debug_ $labels; + }; + my @cust = grep $_->{id} >= 1000, @$labels; + if(@cust) { + br_; + span_ class => 'linkradio', sub { + join_ sub { em_ ' / ' }, \&lblfilt_, @cust; + } + } + br_; + input_ type => 'submit', class => 'submit', value => 'Update filters'; + input_ type => 'button', class => 'submit', id => 'labeledit', value => 'Manage labels' if $own; + }; + }; + elm_ 'ULists.ManageLabels', $LABELS, { uid => $u->{id}, labels => $labels } if $own; + } + }; +}; + + +json_api qr{/u/ulist/labels.json}, $LABELS, sub { + my($uid, $labels) = ($_[0]{uid}, $_[0]{labels}); + return elm_Unauth if !auth || auth->uid != $uid; + + # Insert new labels + my @new = grep $_->{id} < 0 && !$_->{delete}, @$labels; + tuwf->dbExeci( + 'INSERT INTO ulists_labels (uid, label, private)', + 'VALUES ', sql_comma( + map sql('(', sql_comma(\$uid, \$_->{label}, \$_->{private}), ')'), @new + ) + ) if @new; + + # Update private flag + tuwf->dbExeci( + 'UPDATE ulists_labels SET private =', \$_->{private}, + 'WHERE uid =', \$uid, 'AND id =', \$_->{id}, 'AND private <>', \$_->{private} + ) for grep $_->{id} > 0 && !$_->{delete}, @$labels; + + # Update label + tuwf->dbExeci( + 'UPDATE ulists_labels SET label =', \$_->{label}, + 'WHERE uid =', \$uid, 'AND id =', \$_->{id}, 'AND label <>', \$_->{label} + ) for grep $_->{id} >= 1000 && !$_->{delete}, @$labels; + + # Delete labels + my @delete = grep $_->{id} >= 1000 && $_->{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 ulists_vn_labels WHERE uid =', \$uid, 'AND lbl IN', \@delete_all, ')') : (), + @delete_empty ? sql( + 'vid IN(SELECT vid FROM ulists_vn_labels WHERE uid =', \$uid, 'AND lbl IN', \@delete_empty, ')', + 'AND NOT EXISTS(SELECT 1 FROM ulists_vn_labels WHERE uid =', \$uid, 'AND lbl NOT IN(', [ @delete_lblonly, @delete_empty ], '))' + ) : (); + tuwf->dbExeci('DELETE FROM ulists WHERE uid =', \$uid, 'AND (', sql_or(@where), ')') if @where; + + # (This will also delete all relevant vn<->label rows from ulists_vn_labels) + tuwf->dbExeci('DELETE FROM ulists_labels WHERE uid =', \$uid, 'AND id IN', [ map $_->{id}, @delete ]) if @delete; + + elm_Success +}; + +1; |