diff options
author | Yorhel <git@yorhel.nl> | 2022-08-03 14:24:14 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2022-08-03 14:24:14 +0200 |
commit | a74aef240cd270047730cd7931f5d7f35f3701a8 (patch) | |
tree | cfb64e304d24d8ee74ed94e588ea9432b06befe5 | |
parent | f13f03ac6700e0364344b8543842d68d697f2032 (diff) |
AdvSearch: Add option to not match child tags
-rw-r--r-- | elm/AdvSearch/Fields.elm | 11 | ||||
-rw-r--r-- | elm/AdvSearch/Tags.elm | 19 | ||||
-rw-r--r-- | lib/VNWeb/AdvSearch.pm | 34 |
3 files changed, 40 insertions, 24 deletions
diff --git a/elm/AdvSearch/Fields.elm b/elm/AdvSearch/Fields.elm index fa08f585..b933f229 100644 --- a/elm/AdvSearch/Fields.elm +++ b/elm/AdvSearch/Fields.elm @@ -426,10 +426,13 @@ fields = , f V "Language" 1 FMLang (AS.langInit AS.LangVN) (AS.langFromQuery AS.LangVN) , f V "Original language" 2 FMLang (AS.langInit AS.LangVNO) (AS.langFromQuery AS.LangVNO) , f V "Platform" 3 FMVPlatform AS.init AS.platformFromQuery - , f V "Tags" 4 FMTag AG.init (AG.fromQuery -1) - , f V "" -4 FMTag AG.init (AG.fromQuery 0) - , f V "" -4 FMTag AG.init (AG.fromQuery 1) - , f V "" -4 FMTag AG.init (AG.fromQuery 2) + , f V "Tags" 4 FMTag AG.init (AG.fromQuery -1 True) + , f V "" -4 FMTag AG.init (AG.fromQuery 0 True) + , f V "" -4 FMTag AG.init (AG.fromQuery 1 True) + , f V "" -4 FMTag AG.init (AG.fromQuery 2 True) + , f V "" -4 FMTag AG.init (AG.fromQuery 0 False) + , f V "" -4 FMTag AG.init (AG.fromQuery 1 False) + , f V "" -4 FMTag AG.init (AG.fromQuery 2 False) , f V "My Labels" 0 FMLabel AS.init AS.labelFromQuery , l V "My List" 0 [(QInt 65 Eq 1, "On my list"), (QInt 65 Ne 1, "Not on my list")] , f V "Length" 0 FMLength AS.init AS.lengthFromQuery diff --git a/elm/AdvSearch/Tags.elm b/elm/AdvSearch/Tags.elm index 715b8c25..9dfa4e9b 100644 --- a/elm/AdvSearch/Tags.elm +++ b/elm/AdvSearch/Tags.elm @@ -18,12 +18,14 @@ type alias Model = , conf : A.Config Msg GApi.ApiTagResult , search : A.Model GApi.ApiTagResult , spoiler : Int + , inherit : Bool } type Msg = Sel (S.Msg (Int,Int)) | Level (Int,Int) Int | Spoiler + | Inherit Bool | Search (A.Msg GApi.ApiTagResult) @@ -35,6 +37,7 @@ init dat = , conf = { wrap = Search, id = "advsearch_tag" ++ String.fromInt ndat.objid, source = A.tagSource } , search = A.init "" , spoiler = dat.defaultSpoil + , inherit = True } ) @@ -45,6 +48,7 @@ update dat msg model = Sel m -> (dat, { model | sel = S.update m model.sel }, Cmd.none) Level (t,ol) nl -> (dat, { model | sel = S.update (S.Sel (t,ol) False) model.sel |> S.update (S.Sel (t,nl) True) }, Cmd.none) Spoiler -> (dat, { model | spoiler = if model.spoiler < 2 then model.spoiler + 1 else 0 }, Cmd.none) + Inherit b -> (dat, { model | inherit = b }, Cmd.none) Search m -> let (nm, c, res) = A.update model.conf m model.search in case res of @@ -55,12 +59,15 @@ update dat msg model = , c ) -toQuery m = S.toQuery (\o (t,l) -> if m.spoiler == 0 && l == 0 then QInt 8 o t else QTuple 8 o t (l*3+m.spoiler)) m.sel +toQuery m = S.toQuery (\o (t,l) -> + let id = if m.inherit then 8 else 14 + in if m.spoiler == 0 && l == 0 then QInt id o t else QTuple id o t (l*3+m.spoiler)) m.sel -fromQuery spoil dat q = - let f qr = case qr of - QInt 8 op t -> if spoil == 0 then Just (op, (t,0)) else Nothing - QTuple 8 op t v -> if modBy 3 v == spoil then Just (op, (t,v//3)) else Nothing +fromQuery spoil inherit dat q = + let id = if inherit then 8 else 14 + f qr = case qr of + QInt x op t -> if id == x && spoil == 0 then Just (op, (t,0)) else Nothing + QTuple x op t v -> if id == x && modBy 3 v == spoil then Just (op, (t,v//3)) else Nothing _ -> Nothing in S.fromQuery f dat q |> Maybe.map (\(ndat,sel) -> @@ -69,6 +76,7 @@ fromQuery spoil dat q = , conf = { wrap = Search, id = "advsearch_tag" ++ String.fromInt ndat.objid, source = A.tagSource } , search = A.init "" , spoiler = spoil + , inherit = inherit } )) @@ -92,6 +100,7 @@ view dat model = [ text <| if model.spoiler == 0 then "no spoilers" else if model.spoiler == 1 then "minor spoilers" else "major spoilers" ] , linkRadio model.sel.neg (Sel << S.Neg) [ text "invert" ] ] + , div [ class "opts" ] [ span [] [], linkRadio model.inherit Inherit [ text "child tags" ] ] ] , ul [] <| List.map (\(t,l) -> li [ style "overflow" "hidden", style "text-overflow" "ellipsis" ] diff --git a/lib/VNWeb/AdvSearch.pm b/lib/VNWeb/AdvSearch.pm index 39f8a014..27e3f88a 100644 --- a/lib/VNWeb/AdvSearch.pm +++ b/lib/VNWeb/AdvSearch.pm @@ -303,6 +303,7 @@ sub f { $f{vndbid} = ref $v eq 'HASH' && $v->{vndbid} && !ref $v->{vndbid} && $v->{vndbid}; $f{int} = ref $f{value} && ($v->{fuzzyrdate} || $f{value}->analyze->{type} eq 'int' || $f{value}->analyze->{type} eq 'bool'); $FIELDS{$t}{$n} = \%f; + die "Duplicate number $num for $t\n" if $NUMFIELDS{$t}{$num}; $NUMFIELDS{$t}{$num} = $n; } @@ -325,9 +326,8 @@ f v => 64 => 'has-review', { uint => 1, range => [1,1] }, '=' => sub { 'EXI f v => 65 => 'on-list', { uint => 1, range => [1,1] }, '=' => sub { auth ? sql 'v.id IN(SELECT vid FROM ulist_vns WHERE uid =', \auth->uid, ')' : '1=0' }; f v => 66 => 'devstatus', { uint => 1, enum => \%DEVSTATUS }, '=' => sub { 'v.devstatus =', \$_ }; -f v => 8 => 'tag', { type => 'any', func => \&_validate_tag }, - compact => sub { my $id = ($_->[0] =~ s/^g//r)*1; $_->[1] == 0 && $_->[2] == 0 ? $id : [ $id, int($_->[2]*5)*3 + $_->[1] ] }, - sql_list => \&_sql_where_tag; +f v => 8 => 'tag', { type => 'any', func => \&_validate_tag }, compact => \&_compact_tag, sql_list => _sql_where_tag('tags_vn_inherit'); +f v => 14 => 'dtag', { type => 'any', func => \&_validate_tag }, compact => \&_compact_tag, sql_list => _sql_where_tag('tags_vn_direct'); f v => 12 => 'label', { type => 'any', func => \&_validate_label }, compact => sub { [ ($_->[0] =~ s/^u//r)*1, $_->[1]*1 ] }, @@ -487,6 +487,7 @@ sub _validate_tag { 1 } +sub _compact_tag { my $id = ($_->[0] =~ s/^g//r)*1; $_->[1] == 0 && $_->[2] == 0 ? $id : [ $id, int($_->[2]*5)*3 + $_->[1] ] } # Accepts either $trait or [$trait, $maxspoil]. Normalizes to the latter. sub _validate_trait { @@ -595,21 +596,24 @@ sub _canon { } -# sql_list function for tags +# returns an sql_list function for tags sub _sql_where_tag { - my($neg, $all, $val) = @_; - my %f; # spoiler -> rating -> list - my @l; - push $f{$_->[1]}{$_->[2]}->@*, $_->[0] for @$val; - for my $s (keys %f) { - for my $r (keys $f{$s}->%*) { - push @l, sql_and - $s < 2 ? sql('spoiler <=', \$s) : (), - $r > 0 ? sql('rating >=', \$r) : (), - sql('tag IN', $f{$s}{$r}); + my($table) = @_; + sub { + my($neg, $all, $val) = @_; + my %f; # spoiler -> rating -> list + my @l; + push $f{$_->[1]}{$_->[2]}->@*, $_->[0] for @$val; + for my $s (keys %f) { + for my $r (keys $f{$s}->%*) { + push @l, sql_and + $s < 2 ? sql('spoiler <=', \$s) : (), + $r > 0 ? sql('rating >=', \$r) : (), + sql('tag IN', $f{$s}{$r}); + } } + sql 'v.id', $neg ? 'NOT' : (), 'IN(SELECT vid FROM', $table, 'WHERE', sql_or(@l), $all && @$val > 1 ? ('GROUP BY vid HAVING COUNT(tag) =', \scalar @$val) : (), ')' } - sql 'v.id', $neg ? 'NOT' : (), 'IN(SELECT vid FROM tags_vn_inherit WHERE', sql_or(@l), $all && @$val > 1 ? ('GROUP BY vid HAVING COUNT(tag) =', \scalar @$val) : (), ')' } sub _sql_where_trait { |