summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-01-04 15:06:22 +0100
committerYorhel <git@yorhel.nl>2020-01-04 15:06:22 +0100
commit02cef019d30233603dd71cc837f382923cfd699a (patch)
tree4350c7907abbcb23b085bd40db8a9d580e750f81
parent8620f71c6180e06164b2b51f930d94acaa439036 (diff)
ulist: Add ability to save views as default
-rw-r--r--data/style.css9
-rw-r--r--elm/UList/ManageLabels.js1
-rw-r--r--elm/UList/SaveDefault.elm76
-rw-r--r--elm/UList/SaveDefault.js7
-rw-r--r--lib/VNWeb/User/Lists.pm57
-rw-r--r--util/sql/perms.sql6
-rw-r--r--util/sql/schema.sql5
-rw-r--r--util/updates/2020-01-04-ulist-saved-views.sql4
8 files changed, 146 insertions, 19 deletions
diff --git a/data/style.css b/data/style.css
index 108eccb1..b112ccb1 100644
--- a/data/style.css
+++ b/data/style.css
@@ -82,8 +82,8 @@ div.warning h2, div.notice h2 { font-size: 13px; font-weight: bold; margin: 0; }
#ds_box table { width: 100%; }
/* Elm dropdowns */
-.elm_dd > a { color: $maintext$; display: block; border: none!important; padding-right: 10px; position: relative }
-.elm_dd > a > span { position: absolute; right: 0; top: 0; width: 16px; text-align: right; display: block }
+.elm_dd > a { color: $maintext$; display: block; border: none!important; padding-right: 15px; position: relative }
+.elm_dd > a > span { position: absolute; right: 5px; top: 0; width: 16px; text-align: right; display: block }
.elm_dd > a > span i { visibility: hidden; font-style: normal }
.elm_dd > a:hover > span > i,
.elm_dd > a:focus > span > i { visibility: visible }
@@ -92,9 +92,10 @@ div.warning h2, div.notice h2 { font-size: 13px; font-weight: bold; margin: 0; }
.elm_dd.search > div { float: left }
.elm_dd.search > div > ul { right: auto; left: 0; top: 23px }
.elm_dd > div > ul li { white-space: nowrap }
-.elm_dd > div > ul li a { display: block; padding-left: 10px; border: 0; padding: 3px 5px 3px 3px }
+.elm_dd > div > ul li a { display: block; border: 0; padding: 3px 5px 3px 3px }
.elm_dd > div > ul li a.active,
.elm_dd > div > ul li a:hover { background: $boxbg$ }
+.elm_dd > div > ul li p { white-space: normal; padding: 3px 5px 3px 3px }
@@ -822,6 +823,8 @@ div.votelist td.tc2 { width: 50px; text-align: right; padding-right: 10px }
.managelabels select { width: 100% }
.managelabels tfoot div { float: right; text-align: right }
+.savedefault { width: 600px; margin: 10px auto }
+
.ulist .tc1 { white-space: nowrap; width: 70px }
.ulist .tc1 label { cursor: pointer }
.ulist .tc1 input { display: none }
diff --git a/elm/UList/ManageLabels.js b/elm/UList/ManageLabels.js
index 41ea1c12..6f762bd8 100644
--- a/elm/UList/ManageLabels.js
+++ b/elm/UList/ManageLabels.js
@@ -1,6 +1,7 @@
document.querySelectorAll('#managelabels').forEach(function(b) {
b.onclick = function() {
document.querySelectorAll('.managelabels').forEach(function(e) { e.classList.toggle('hidden') })
+ document.querySelectorAll('.savedefault').forEach(function(e) { e.classList.add('hidden') })
};
return false;
});
diff --git a/elm/UList/SaveDefault.elm b/elm/UList/SaveDefault.elm
new file mode 100644
index 00000000..42fdef84
--- /dev/null
+++ b/elm/UList/SaveDefault.elm
@@ -0,0 +1,76 @@
+module UList.SaveDefault exposing (main)
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import Browser
+import Lib.Html exposing (..)
+import Lib.Util exposing (..)
+import Lib.Api as Api
+import Gen.Api as GApi
+import Gen.UListSaveDefault as GUSD
+
+
+main : Program GUSD.Recv Model Msg
+main = Browser.element
+ { init = \e -> (init e, Cmd.none)
+ , view = view
+ , update = update
+ , subscriptions = always Sub.none
+ }
+
+type alias Model =
+ { state : Api.State
+ , uid : Int
+ , opts : GUSD.SendOpts
+ , field : String -- Ewwww stringly typed enum
+ , hid : Bool
+ }
+
+init : GUSD.Recv -> Model
+init d =
+ { state = Api.Normal
+ , uid = d.uid
+ , opts = d.opts
+ , field = "vnlist"
+ , hid = True
+ }
+
+type Msg
+ = SetField String
+ | Submit
+ | Submitted GApi.Response
+
+
+update : Msg -> Model -> (Model, Cmd Msg)
+update msg model =
+ case msg of
+ SetField s -> ({ model | field = s, hid = False }, Cmd.none)
+
+ Submit ->
+ ( { model | state = Api.Loading, hid = False }
+ , Api.post "/u/ulist/savedefault.json" (GUSD.encode { uid = model.uid, opts = model.opts, field = model.field }) Submitted)
+ Submitted GApi.Success -> ({ model | state = Api.Normal, hid = True }, Cmd.none)
+ Submitted r -> ({ model | state = Api.Error r }, Cmd.none)
+
+
+view : Model -> Html Msg
+view model =
+ form_ Submit (model.state == Api.Loading)
+ [ div [ classList [("savedefault", True), ("hidden", model.hid)] ]
+ [ b [] [ text "Save as default" ]
+ , br [] []
+ , text "This will change the default label selection, visible columns and table sorting options for the selected page to the currently applied settings."
+ , text " The saved view will also apply to users visiting your lists."
+ , br [] []
+ , text "(If you just changed the label filters, make sure to hit \"Update filters\" before saving)"
+ , br [] []
+ , label [] [ inputRadio "savedefault_page" (model.field == "votes") (always (SetField "votes") ), text " My Votes" ]
+ , br [] []
+ , label [] [ inputRadio "savedefault_page" (model.field == "vnlist") (always (SetField "vnlist")), text " My Visual Novel List" ]
+ , br [] []
+ , label [] [ inputRadio "savedefault_page" (model.field == "wish") (always (SetField "wish") ), text " My Wishlist" ]
+ , br [] []
+ , submitButton "Save" model.state True
+ ]
+ ]
diff --git a/elm/UList/SaveDefault.js b/elm/UList/SaveDefault.js
new file mode 100644
index 00000000..a253680f
--- /dev/null
+++ b/elm/UList/SaveDefault.js
@@ -0,0 +1,7 @@
+document.querySelectorAll('#savedefault').forEach(function(b) {
+ b.onclick = function() {
+ document.querySelectorAll('.savedefault').forEach(function(e) { e.classList.toggle('hidden') })
+ document.querySelectorAll('.managelabels').forEach(function(e) { e.classList.add('hidden') })
+ };
+ return false;
+});
diff --git a/lib/VNWeb/User/Lists.pm b/lib/VNWeb/User/Lists.pm
index bc806c2c..9620eb80 100644
--- a/lib/VNWeb/User/Lists.pm
+++ b/lib/VNWeb/User/Lists.pm
@@ -236,7 +236,7 @@ my $VNADD = form_compile any => {
elm_form 'UListAdd', undef, $VNADD;
-json_api qr{/u/ulist/add\.json}, $VNDEL, sub {
+json_api qr{/u/ulist/add\.json}, $VNADD, sub {
my($data) = @_;
return elm_Unauth if !own $data->{uid};
tuwf->dbExeci('INSERT INTO ulist_vns', $data, 'ON CONFLICT (uid, vid) DO NOTHING');
@@ -270,24 +270,55 @@ json_api qr{/u/ulist/rstatus\.json}, $RSTATUS, sub {
+
+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_form UListSaveDefault => $SAVED_OPTS_OUT, $SAVED_OPTS_IN;
+
+json_api qr{/u/ulist/savedefault\.json}, $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($filtlabels) = @_;
+ my($u, $filtlabels) = @_;
+
+ my sub load { my $o = $u->{"ulist_$_[0]"}; ($o && eval { JSON::XS->new->decode($o) } or {})->%* };
my $opt =
# Presets
- tuwf->reqGet('vnlist') ? { mul => 0, p => 1, l => [1,2,3,4,7,-1,0], s => 'title', o => 'a', c => [qw/label vote added started finished/] } :
- tuwf->reqGet('votes') ? { mul => 0, p => 1, l => [7], s => 'voted', o => 'd', c => [qw/vote voted/] } :
- tuwf->reqGet('wishlist') ? { mul => 0, p => 1, l => [5], s => 'title', o => 'a', c => [qw/label added/] } :
+ tuwf->reqGet('vnlist') ? { mul => 0, p => 1, l => [1,2,3,4,7,-1,0], s => 'title', o => 'a', c => [qw/label vote added started finished/], load 'vnlist' } :
+ tuwf->reqGet('votes') ? { mul => 0, p => 1, l => [7], s => 'voted', o => 'd', c => [qw/vote voted/], load 'votes' } :
+ tuwf->reqGet('wishlist') ? { mul => 0, p => 1, l => [5], s => 'title', o => 'a', c => [qw/label added/], load 'wishlist' } :
# Full options
tuwf->validate(get =>
p => { upage => 1 },
- l => { onerror => [], type => 'array', scalar => 1, values => { int => 1 } },
- s => { onerror => 'title', enum => [qw[ title label vote voted added modified started finished rel rating ]] },
- o => { onerror => 'a', enum => ['a', 'd'] },
- c => { onerror => [], type => 'array', scalar => 1, values => { enum => [qw[ label vote voted added modified started finished rel rating ]] } },
ch=> { onerror => undef, enum => [ 'a'..'z', 0 ] },
q => { required => 0 },
- mul => { anybool => 1 },
+ %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
@@ -343,6 +374,7 @@ sub filters_ {
br_;
input_ type => 'submit', class => 'submit', tabindex => 10, value => 'Update filters';
input_ type => 'button', class => 'submit', tabindex => 10, id => 'managelabels', value => 'Manage labels' if $own;
+ input_ type => 'button', class => 'submit', tabindex => 10, id => 'savedefault', value => 'Save as default' if $own;
};
};
}
@@ -524,7 +556,7 @@ sub listing_ {
# TODO: Ability to add VNs from this page
TUWF::get qr{/$RE{uid}/ulist}, sub {
- my $u = tuwf->dbRowi('SELECT id,', sql_user(), 'FROM users u WHERE id =', \tuwf->capture('id'));
+ 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};
@@ -551,7 +583,7 @@ TUWF::get qr{/$RE{uid}/ulist}, sub {
} : (),
];
- my($opt, $opt_labels) = opt $filtlabels;
+ my($opt, $opt_labels) = opt $u, $filtlabels;
my sub url { '?'.query_encode %$opt, @_ }
# This page has 3 user tabs: list, wish and votes; Select the appropriate active tab based on label filters.
@@ -577,6 +609,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;
}
};
listing_ $u->{id}, $own, $opt, $labels, \&url if !$empty;
diff --git a/util/sql/perms.sql b/util/sql/perms.sql
index e649526f..b4833a60 100644
--- a/util/sql/perms.sql
+++ b/util/sql/perms.sql
@@ -67,9 +67,9 @@ GRANT SELECT, INSERT, UPDATE, DELETE ON ulist_vns_labels TO vndb_site;
-- users table is special; The 'perm', 'passwd' and 'mail' columns are
-- protected and can only be accessed through the user_* functions.
-GRANT SELECT (id, username, registered, perm, c_votes, c_changes, ip, c_tags, ign_votes, email_confirmed, skin, customcss, filter_vn, filter_release, show_nsfw, hide_list, notify_dbedit, notify_announce, vn_list_own, vn_list_wish, tags_all, tags_cont, tags_ero, tags_tech, spoilers, traits_sexual, nodistract_can, nodistract_noads, nodistract_nofancy, support_can, support_enabled, uniname_can, uniname, pubskin_can, pubskin_enabled, c_vns, c_wish),
- INSERT (id, username, mail, registered, c_votes, c_changes, ip, c_tags, ign_votes, email_confirmed, skin, customcss, filter_vn, filter_release, show_nsfw, hide_list, notify_dbedit, notify_announce, vn_list_own, vn_list_wish, tags_all, tags_cont, tags_ero, tags_tech, spoilers, traits_sexual, nodistract_can, nodistract_noads, nodistract_nofancy, support_can, support_enabled, uniname_can, uniname, pubskin_can, pubskin_enabled, c_vns, c_wish),
- UPDATE ( username, registered, c_votes, c_changes, ip, c_tags, ign_votes, email_confirmed, skin, customcss, filter_vn, filter_release, show_nsfw, hide_list, notify_dbedit, notify_announce, vn_list_own, vn_list_wish, tags_all, tags_cont, tags_ero, tags_tech, spoilers, traits_sexual, nodistract_can, nodistract_noads, nodistract_nofancy, support_can, support_enabled, uniname_can, uniname, pubskin_can, pubskin_enabled, c_vns, c_wish) ON users TO vndb_site;
+GRANT SELECT (id, username, registered, perm, c_votes, c_changes, ip, c_tags, ign_votes, email_confirmed, skin, customcss, filter_vn, filter_release, show_nsfw, hide_list, notify_dbedit, notify_announce, vn_list_own, vn_list_wish, tags_all, tags_cont, tags_ero, tags_tech, spoilers, traits_sexual, nodistract_can, nodistract_noads, nodistract_nofancy, support_can, support_enabled, uniname_can, uniname, pubskin_can, pubskin_enabled, c_vns, c_wish, ulist_votes, ulist_vnlist, ulist_wish),
+ INSERT (id, username, mail, registered, c_votes, c_changes, ip, c_tags, ign_votes, email_confirmed, skin, customcss, filter_vn, filter_release, show_nsfw, hide_list, notify_dbedit, notify_announce, vn_list_own, vn_list_wish, tags_all, tags_cont, tags_ero, tags_tech, spoilers, traits_sexual, nodistract_can, nodistract_noads, nodistract_nofancy, support_can, support_enabled, uniname_can, uniname, pubskin_can, pubskin_enabled, c_vns, c_wish, ulist_votes, ulist_vnlist, ulist_wish),
+ UPDATE ( username, registered, c_votes, c_changes, ip, c_tags, ign_votes, email_confirmed, skin, customcss, filter_vn, filter_release, show_nsfw, hide_list, notify_dbedit, notify_announce, vn_list_own, vn_list_wish, tags_all, tags_cont, tags_ero, tags_tech, spoilers, traits_sexual, nodistract_can, nodistract_noads, nodistract_nofancy, support_can, support_enabled, uniname_can, uniname, pubskin_can, pubskin_enabled, c_vns, c_wish, ulist_votes, ulist_vnlist, ulist_wish) ON users TO vndb_site;
GRANT SELECT, INSERT, UPDATE ON vn TO vndb_site;
GRANT SELECT, INSERT, DELETE ON vn_anime TO vndb_site;
diff --git a/util/sql/schema.sql b/util/sql/schema.sql
index 3bc27c77..f2cc611c 100644
--- a/util/sql/schema.sql
+++ b/util/sql/schema.sql
@@ -782,7 +782,10 @@ CREATE TABLE users (
pubskin_can boolean NOT NULL DEFAULT FALSE,
pubskin_enabled boolean NOT NULL DEFAULT FALSE,
c_vns integer NOT NULL DEFAULT 0,
- c_wish integer NOT NULL DEFAULT 0
+ c_wish integer NOT NULL DEFAULT 0,
+ ulist_votes jsonb,
+ ulist_vnlist jsonb,
+ ulist_wish jsonb
);
-- vn
diff --git a/util/updates/2020-01-04-ulist-saved-views.sql b/util/updates/2020-01-04-ulist-saved-views.sql
new file mode 100644
index 00000000..14926ba6
--- /dev/null
+++ b/util/updates/2020-01-04-ulist-saved-views.sql
@@ -0,0 +1,4 @@
+ALTER TABLE users ADD COLUMN ulist_votes jsonb;
+ALTER TABLE users ADD COLUMN ulist_vnlist jsonb;
+ALTER TABLE users ADD COLUMN ulist_wish jsonb;
+\i util/sql/perms.sql