summaryrefslogtreecommitdiff
path: root/lib/VNWeb
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-12-31 09:35:07 +0100
committerYorhel <git@yorhel.nl>2021-01-03 10:39:57 +0100
commit65e36750ec6ed95d82529146887dd82b2e9dde1c (patch)
treee28d26909bf2e0f94cebbca54ca9d96306b53253 /lib/VNWeb
parent61cb7cd185fbf9203041ca366a2eb915e746d6f4 (diff)
AdvSearch: Add feature to save/load/delete queries
Diffstat (limited to 'lib/VNWeb')
-rw-r--r--lib/VNWeb/AdvSearch.pm34
-rw-r--r--lib/VNWeb/Elm.pm13
-rw-r--r--lib/VNWeb/Misc/AdvSearch.pm40
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;