diff options
author | Yorhel <git@yorhel.nl> | 2020-12-31 09:35:07 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2021-01-03 10:39:57 +0100 |
commit | 65e36750ec6ed95d82529146887dd82b2e9dde1c (patch) | |
tree | e28d26909bf2e0f94cebbca54ca9d96306b53253 /lib/VNWeb | |
parent | 61cb7cd185fbf9203041ca366a2eb915e746d6f4 (diff) |
AdvSearch: Add feature to save/load/delete queries
Diffstat (limited to 'lib/VNWeb')
-rw-r--r-- | lib/VNWeb/AdvSearch.pm | 34 | ||||
-rw-r--r-- | lib/VNWeb/Elm.pm | 13 | ||||
-rw-r--r-- | lib/VNWeb/Misc/AdvSearch.pm | 40 |
3 files changed, 73 insertions, 14 deletions
diff --git a/lib/VNWeb/AdvSearch.pm b/lib/VNWeb/AdvSearch.pm index 5ff0a5ed..26e06561 100644 --- a/lib/VNWeb/AdvSearch.pm +++ b/lib/VNWeb/AdvSearch.pm @@ -282,7 +282,7 @@ sub _enc_query { # # An implementation for the '!=' operator will be supplied automatically if it's not explicitely defined. # NOTE: That implementation does NOT work for NULL values. -my(%FIELDS, %NUMFIELDS); +our(%FIELDS, %NUMFIELDS); sub f { my($t, $num, $n, $v, @opts) = @_; my %f = ( @@ -641,6 +641,9 @@ sub sql_where { } +sub json { shift->{query} } + + sub _compact_json { my($t, $q) = @_; return [ $q->[0] eq 'and' ? 0 : 1, map _compact_json($t, $_), @$q[1..$#$q] ] if $q->[0] eq 'and' || $q->[0] eq 'or'; @@ -678,7 +681,8 @@ sub _extract_ids { } -sub elm_ { +# Returns a JSON object suitable for the AdvSearchQuery API response. +sub elm_search_query { my($self) = @_; my(%o,%ids); @@ -702,23 +706,27 @@ sub elm_ { $o{qtype} = $self->{type}; $o{query} = $self->compact_json; - $o{uid} = auth->uid; - $o{labels} = auth ? tuwf->dbAlli('SELECT id, label FROM ulist_labels WHERE uid =', \auth->uid, 'ORDER BY CASE WHEN id < 10 THEN id ELSE 10 END, label') : []; - $o{defaultSpoil} = auth->pref('spoilers')||0; + \%o +} + + +sub elm_ { + my($self) = @_; state $schema ||= tuwf->compile({ type => 'hash', keys => { - qtype => {}, - query => { type => 'array', required => 0 }, uid => { uint => 1, required => 0 }, labels => { aoh => { id => { uint => 1 }, label => {} } }, defaultSpoil => { uint => 1 }, - producers => $VNWeb::Elm::apis{ProducerResult}[0], - staff => $VNWeb::Elm::apis{StaffResult}[0], - tags => $VNWeb::Elm::apis{TagResult}[0], - traits => $VNWeb::Elm::apis{TraitResult}[0], - anime => $VNWeb::Elm::apis{AnimeResult}[0], + saved => { aoh => { name => {}, query => {} } }, + query => $VNWeb::Elm::apis{AdvSearchQuery}[0], }}); - VNWeb::HTML::elm_ 'AdvSearch.Main', $schema, \%o; + VNWeb::HTML::elm_ 'AdvSearch.Main', $schema, { + uid => auth->uid, + labels => auth ? tuwf->dbAlli('SELECT id, label FROM ulist_labels WHERE uid =', \auth->uid, 'ORDER BY CASE WHEN id < 10 THEN id ELSE 10 END, label') : [], + defaultSpoil => auth->pref('spoilers')||0, + saved => auth ? tuwf->dbAlli('SELECT name, query FROM saved_queries WHERE uid =', \auth->uid, ' AND qtype =', \$self->{type}, 'ORDER BY name') : [], + query => $self->elm_search_query(), + }; } diff --git a/lib/VNWeb/Elm.pm b/lib/VNWeb/Elm.pm index 0fd24d36..96ccc583 100644 --- a/lib/VNWeb/Elm.pm +++ b/lib/VNWeb/Elm.pm @@ -155,6 +155,16 @@ our %apis = ( } }, } } ], ); +# (These references to other API results cause redundant Elm code - can be deduplicated) +$apis{AdvSearchQuery} = [ { type => 'hash', keys => { # Response to 'AdvSearchLoad' + qtype => {}, + query => { type => 'any' }, + producers => $apis{ProducerResult}[0], + staff => $apis{StaffResult}[0], + tags => $apis{TagResult}[0], + traits => $apis{TraitResult}[0], + anime => $apis{AnimeResult}[0], +} } ], # Compile %apis into a %schema and generate the elm_Response() functions @@ -196,6 +206,7 @@ sub def_type { $data .= def_type($name . to_camel($_), $obj->{keys}{$_}{values} || bless { $obj->{keys}{$_}->%*, required => 1 }, ref $obj->{keys}{$_} ) for @keys; $data .= sprintf "\ntype alias %s = %s\n\n", $name, $obj->elm_type( + any => 'JE.Value', keys => +{ map { my $t = $obj->{keys}{$_}; my $n = $name . to_camel($_); @@ -235,7 +246,7 @@ sub def_validation { # Generate an Elm JSON encoder taking a corresponding def_type() as input sub encoder { my($name, $type, $obj) = @_; - def $name, "$type -> JE.Value", $obj->elm_encoder(json_encode => 'JE.'); + def $name, "$type -> JE.Value", $obj->elm_encoder(any => ' ', json_encode => 'JE.'); } diff --git a/lib/VNWeb/Misc/AdvSearch.pm b/lib/VNWeb/Misc/AdvSearch.pm new file mode 100644 index 00000000..61b9af48 --- /dev/null +++ b/lib/VNWeb/Misc/AdvSearch.pm @@ -0,0 +1,40 @@ +package VNWeb::Misc::AdvSearch; + +use VNWeb::Prelude; +use VNWeb::AdvSearch; + + +elm_api 'AdvSearchSave' => undef, { + name => { length => [1,50] }, + qtype => { enum => \%VNWeb::AdvSearch::FIELDS }, + query => {}, +}, sub { + my($d) = @_; + my $q = tuwf->compile({ advsearch => $d->{qtype} })->validate($d->{query})->data->query_encode; + tuwf->dbExeci( + 'INSERT INTO saved_queries', { uid => auth->uid, qtype => $d->{qtype}, name => $d->{name}, query => $q }, + 'ON CONFLICT (uid, qtype, name) DO UPDATE SET query =', \$q + ); + elm_Success +}; + + +elm_api 'AdvSearchDel' => undef, { + name => { type => 'array', minlength => 1, values => { length => [1,50] } }, + qtype => { enum => \%VNWeb::AdvSearch::FIELDS }, +}, sub { + my($d) = @_; + tuwf->dbExeci('DELETE FROM saved_queries WHERE uid =', \auth->uid, 'AND qtype =', \$d->{qtype}, 'AND name IN', $d->{name}); + elm_Success +}; + + +elm_api 'AdvSearchLoad' => undef, { + qtype => { enum => \%VNWeb::AdvSearch::FIELDS }, + query => {}, +}, sub { + my($d) = @_; + elm_AdvSearchQuery tuwf->compile({ advsearch => $d->{qtype} })->validate($d->{query})->data->elm_search_query; +}; + +1; |